设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

Swift开发iOS应用教程

2014-6-23 12:03| 发布者: joejoe0332| 查看: 7736| 评论: 0|原作者: 几点人, GoodLoser, Garfielt, 地狱星星, 0x0bject|来自: oschina

摘要: 苹果最近宣布了一个改变iOS应用既往开发的一个大变化,一种取代Objective-C称为Swift的完全不同的编程语言。我正在努力学习这门新语言,而且我决定将按照我的学习进程定期发布并共享我所找到的内容。这是众多主题的 ...


  接受响应


  现在我们将要添加目前为止最长的代码块了,不过依旧不是很长,用来处理整个的结果信息。

01func connection(didReceiveResponse: NSURLConnection!, 
02            didReceiveResponse response: NSURLResponse!) {
03   // Recieved a new request, clear out the data object
04   self.data = NSMutableData()
05}
06 
07func connection(connection: NSURLConnection!, 
08                                        didReceiveData data: NSData!) {
09   // Append the recieved chunk of data to our data object
10   self.data.appendData(data)
11}
12 
13func connectionDidFinishLoading(connection: NSURLConnection!) {
14   // Request complete, self.data should now hold the resulting info
15   // Convert the retrieved data in to an object through 
16   // JSON deserialization
17   var err: NSError
18   var jsonResult: NSDictionary = 
19                NSJSONSerialization.JSONObjectWithData(data, 
20                options:    NSJSONReadingOptions.MutableContainers, 
21                error: nil) as NSDictionary
22 
23   if jsonResult.count>0 && jsonResult["results"].count>0 {
24      var results: NSArray = jsonResult["results"] as NSArray
25      self.tableData = results
26      self.appsTableView.reloadData()
27 
28   }
29}


  当NSURLConnection 接受到一个响应,我们可能期望 didReceiveResponse方法代表我们被调用。此时我们可以简单的重置我们的数据,通过 self.data = NSMutableData()来创建一个新的空的Data对象。


  连接建立后,我们将开始在didReceiveData中接受数据。这里传递的数据参数是我们所有信息的来源。我们需要抓住传递进来的每一块数据,因此我们将它添加到 self.data对象(我们之前清理过的)的结尾。


  当连接最终完成并且所有数据都被接收到,connectionDidFinishLoading方法被调用并且我们可以在我们的应用中使用这些数据了,太棒了。


  这里connectionDidFinishLoading方法使用NSJSONSerialization类通过反序列换来自iTune的结果来将我们的原始数据转化为有用的字典对象。


  现在,因为我们知道来自iTunes的数据格式略显粗糙,因此一个简单的对“result”键数量的检查足以判断是否是我们想要的数据了。所以我们现在可以设置我们的self.tableData对象为结果数据,并且告诉  appsTableView 去加载内容。这会引起Table View对象运行他自己的委托方法。定义这些是我们教程的最后一步了。


更新Table View UI


你可能还记得上一次我们为Table View完成了两个功能。计数功能决定了行数; 单元格功能,真正的在每一行创建和修改单元格.

我们将要更新Table View使用我们从web下载的数据.

换出你的方法有以下两个功能:

func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
   return tableData.count
}

   func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
   let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell")

   var rowData: NSDictionary = self.tableData[indexPath.row] as NSDictionary

   cell.text = rowData["trackName"] as String

   // Grab the artworkUrl60 key to get an image URL for the app's thumbnail
   var urlString: NSString = rowData["artworkUrl60"] as NSString
   var imgURL: NSURL = NSURL(string: urlString)

   // Download an NSData representation of the image at the URL
   var imgData: NSData = NSData(contentsOfURL: imgURL)
   cell.image = UIImage(data: imgData)

   // Get the formatted price string for display in the subtitle
   var formattedPrice: NSString = rowData["formattedPrice"] as NSString

   cell.detailTextLabel.text = formattedPrice

   return cell
}

numberOfRowsInSection简单的从tableData成员返回结果对象的数量, 并设置我们前面的connectionDidFinishLoading方法.

在这个例子中cellForRowAtIndexPath也不会明显的改变。 而是简单的返回行数, 我们使用行数获取三个信息: 曲目名称, 作品的网址和价格.

使用这些关键字,我们在单元格中构建了标题,副标题和图片。

尝试运行我们的APP,你将第一次看到我们完全使用Swift真正创建了一些看起来像APP的东西。

这部分教程最终的代码可以在这儿找到。


为什么反应还是这么迟缓!?

  在这个表格视图里,我们没能正确地处理许多事情。在接下来的三个小节里,我们将深入探讨问题在哪儿和我们需要正确地做出那些修改。如果你愿意的话,可以跳到第五部分,在第五部分这些问题都得到了解决。


  以后再第三部分,我们将关注的应用的交互部分,这样用户就可以搜索他要找的任何东西,而且可以点击表格。


  在第一部分和第二部分,我们研究的是Swift基础余元部分,并建立了一个简单的项目例子:创建表格视图,把从iTunes搜索的API结果放入表格里。如果你还仍然还没有阅读这些内容,那么请查看第一部分第二部分


  在这一小节里,我们先暂时停下来,然后清除目前状况下我们所创建的部分代码:删除视图控制器代码里的网络逻辑,然后修补一些影响性能的问题。做这些工作可能不是编写一个新应用中最吸引人的地方,但却非常重要!我们一起完成这些工作吧...


分离代码


  先说重要的, 让我们用一些更有意义的名字来重命名我们的View Controller。打开你的 ViewController.swift文件并且将‘ViewController’ 替换为我们的新名字‘SearchResultViewController’。当然也要重命名文件为SearchResultViewController.swift。


  如果你现在运行程序肯定会崩溃的。这是因为我们的storyboard文件还没有被更新呢。因此打开Main.storyboard文件,在这个界面(左边导航栏)选择你的‘View Controller’对象,然后选择身份检查器(右边,第三个按钮)。


  在这让我们把‘ViewController’类名改为‘SearchResultViewController’。现在我们应该可以回到正轨了。检查项目是否正常工作,然后我们继续。


  

  现在,我们将把类里的API代码移到外部。在xcode导航面板按鼠标右键,然后选择‘新建文件...'。这时就会进入iOS->代码导航下的Cocoa Touch类。


  这个文件将处理所有API的工作,因此我们称它为APIController。


  然后,我们选取searchItunesFor()函数和所有像connection(didRecieveResponse...)这样的委托代理函数。把它们从Search controller剪切出来,然后黏贴到APIController里。你还需要拷贝哪些生成响应所需的数据变量。


如果你立刻进行构建,你会看到一下三个错误:

1) SearchResultsViewController当前没有定义searchItunesFor(); 
2) APIController当前没有定义self.tableData 

3)APIController当前没有定义self.appsTableView


  为了解决以上问题,我们需要让这些对象之间可以互相识别。因此要使APIController为SearchResultViewController的子对象。要做到这些非常容易,只要在SearchResultsViewController类定义的底部添加以下一行: 

1var api:APIController = APIController()

然后修改调用searchItunesFor()哪行为: 

1api.searchItunesFor("Angry Birds")


  在这里,唯一不同点是通过APIController实例调用了这个方法,而不是一步完成所有的处理过程。


  在要留心第一种错误同时,还需要APIController把结果返回给SearchResultViewController。我们希望API controller能够响应任何API调用,因此我们还应当定义一个通信协议,视图可通过这个通信协议获取到响应。


定义API协议


  引用tableData结果的APIController目前有两行错误,我们暂时先删除它们,使用更干净清晰一些的东西。


  在我们的APIController 类定义之上,我们添加一个声明了待实现的didReceiveAPIResults函数的协议。

1protocol APIControllerProtocol {
2   func didRecieveAPIResults(results: NSDictionary)
3}


  他自己并不做任何事情,但是现在我们可以将这个协议添加到我们的SearchResultViewController中。现在不遵守协议就会引发错误,因此我们不会再犯没有实现didReceiveAPIResults的低级错误了。


遵守协议

  现在修改你的SearchResultsViewController来遵守协议:

1class SearchResultsViewController: UIViewController, UITableViewDataSource, 
2UITableViewDelegate, APIControllerProtocol {


  现在编译应该会得到一个SearchResultsViewController没有遵守 APIControllerProtocol协议的错误,很好!现在我们只需向我们的SearchResultsViewController类中添加函数就可以了。他看起来将非常像我们前面connectionDidFinishLoading类的内容。


1func didRecieveAPIResults(results: NSDictionary) {
2   // Store the results in our table data array
3   if results.count>0 {
4      self.tableData = results["results"] as NSArray
5      self.appsTableView.reloadData()
6   }
7}


  还有一件需要做的事情是改变我们的API controller使其包含一个委托对象,并且当连接完成一些API数据的加载后调用这个方法。


使用协议


  返回APIController.swift文件,让我们在类定义下增加一个委托。

var delegate: APIControllerProtocol?


  结尾的问号表示委托是一个可选值。没有问号,我们将获得一个编译错误,提示没有为变量设置初始值,但是对我们来说是不会有这个错误提示的。可以在任何类中定义委托对象,只要它通过didRecieveAPIResults()方法附着到APIControllerProtocol中,因为我们在SearchResultsViewController已经完成上述工作。


  现在我们已经添加了一个委托变量,让我们返回到SearchResultsViewController,在方法viewDidLoad中,让我们设置我们的api控制器的委托到自身,因此它可以接受委托函数的调用。


self.api.delegate = self


  最后,在connectionDidFinishLoading方法中,让我们移除tableView代码并使用我们华丽的新协议方法替换它。


func connectionDidFinishLoading(connection: NSURLConnection!) {
   // Request complete, self.data should now hold the resulting info
   // Convert the retrieved data in to an object through JSON deserialization
   var err: NSError
   var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary

   // Now send the JSON result to our delegate object
   delegate?.didRecieveAPIResults(jsonResult)
}


吁,稍休息一下!

  到现在为止,我知道所创建的应用都是些样例应用,而且应用也确实像以前一样可以做相同的事情,不过我们在许多方面都拥有了更多的灵活性。现在,我们使用APIController来实现对iTunes搜索API的调用,并让一个定制的代理来接收响应。我认为目前我们把所有的时间都用在这些事情上,因此在第四部分我们将关注的是交互方面。如果你打算继续向下阅读,请通过email注册一下


  这一小节中的全部代码在这儿可以找到。


  在第一、第二和第三部分,我们回顾了Swift的一些基础知识,并创建了一个简单示例项目:创建表格视图,并把iTunes的API返回结果放到这些表格里。如果你到现在还没有阅读到这些内容,那么请阅读第一第二第三部分


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部