学习自 Developing iOS Apps Using Swift
之前在一个单独文件中实现了在 iTunes 中搜索 应用名称并显示出来,代码如下:
import UIKit
class SearchResultsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet var appsTableView: UITableView
var tableData: NSArray = []
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.textLabel.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.imageView.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
}
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.textLabel.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.imageView.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
}
override func viewDidLoad() {
super.viewDidLoad()
api.searchItunesFor("Angry Birds")
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
但这种实现的问题在于它不符合 iOS 开发中提倡的 MVC 设计模式,所谓 MVC ,即是「Model, View, Controller」分离实现。
上面的代码将 Model 和 Control 放在了一个文件中了,下面我们将它分离开来。
###一
首先新建一个 Swift 文件,名为 APIController.swift ,并将 searchItunesFor 函数移入 APIController.swift 文件中。
这时 Xcode 会提示三个错误,分别是:
- searchItunesFor() is now undefined in out SearchResultsViewController.
- self.tableData is now undefined in APIController.
- self.appsTableView is now undefined in the APIController.
###二
为解决第一个错误,我们需要在 SearchResultsViewController 中实例化 APIController。
在 ViewController 中声明 APIController 的实例:
var api: APIController = APIController
并将原来的调用 searchItunesFor() 变为:
api.searchItunesFor("Angry Birds")
###三
下一步我们需要把 APIController 中产生的结果传回给 ViewController。
这里首先在 APIController 中定义一个协议如下:
protocol APIControllerProtocol {
func didReceiveAPIResults(results: NSDictionary)
}
然后让 ViewController 继承该协议:
class SearchResultsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, APIControllerProtocol {
在 ViewController 中声明协议要求的函数:
func didReceiveAPIResults(results: NSDictionary) {
var resultsArr: NSArray = results["results"] as NSArray
dispatch_async(dispatch_get_main_queue(), {
self.tableData = resultsArr
self.appsTableView.reloadData()
})
}
使用协议来传递结果的方法是,先在 APIController 中声明一个代理:
var delegate: APIControllerProtocol?
然后在 ViewController 中的 viewDidLoad 函数中定义该代理:
self.api.delegate = self
最后进行数据传递,将
dispatch_async(dispatch_get_main_queue(), {
self.tableData = resultsArr
self.appsTableView.reloadData()
})
改为
self.delegate?.didReveiveAPIResults(jsonResult)
即可
END