对于Massive View Controller,现在流行的解决方案是MVVM架构,把业务逻辑移入ViewModel来减少ViewController中的代码。
这几天又看到另一种方案,在此介绍一下。
例子
我们通过例子来说明,这里举的例子是一个常见的基于TableView的界面——一个通讯录用户信息列表。
我们要实现的业务流程如下
App启动后首先读取本地Core Data中的数据,并展现出来,然后调用Web API来获取到用户数据列表,然后更新本地Core Data数据库,只要数据更新了,UI上的展现也随之变化。
用户也可以在本地添加用户数据,然后这些数据会同步到服务端。
1. 声明协议
我们不会把所有的业务逻辑都写到ViewController里,而是首先声明两个protocol:
PeopleListDataProviderProtocol
定义了数据源对象要实现的属性和方法
1 2 3 4 5 6 7 |
public protocol PeopleListDataProviderProtocol: UITableViewDataSource { var managedObjectContext: NSManagedObjectContext? { get set } weak var tableView: UITableView! { get set } func addPerson(personInfo: PersonInfo) func fetch() } |
APICommunicatorProtocol
定义了API请求者要实现的属性和方法
1 2 3 4 |
public protocol APICommunicatorProtocol { func getPeople() -> (NSError?, [PersonInfo]?) func postPerson(personInfo: PersonInfo) -> NSError? } |
2. 编写ViewController
我们的ViewController叫做PeopleListViewController,在其中声明两个属性:
1 2 |
public var dataProvider: PeopleListDataProviderProtocol? public var communicator: APICommunicatorProtocol = APICommunicator() |
实现ViewDidLoad
1 2 3 4 5 6 7 8 9 10 11 |
override public func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.navigationItem.leftBarButtonItem = self.editButtonItem() let addButton = UIBarButtonItem(barButtonSystemItem: .Add, target: self, action: "addPerson") self.navigationItem.rightBarButtonItem = addButton // ViewController继承于UITableViewController assert(dataProvider != nil, "dataProvider is not allowed to be nil at this point") tableView.dataSource = dataProvider dataProvider?.tableView = tableView } |
添加按钮的事件响应方法和回调:
1 2 3 4 5 6 7 8 9 10 11 |
func addPerson() { let picker = ABPeoplePickerNavigationController() picker.peoplePickerDelegate = self presentViewController(picker, animated: true, completion: nil) } extension PeopleListViewController: ABPeoplePickerNavigationControllerDelegate { public func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController, didSelectPerson person: ABRecord) { let personInfo = PersonInfo(abRecord: person) dataProvider?.addPerson(personInfo) } } |
然后再添加两个方法来请求和同步数据:
1 2 3 4 5 6 7 8 9 10 11 |
public func fetchPeopleFromAPI() { let allPersonInfos = communicator.getPeople().1 if let allPersonInfos = allPersonInfos { for personInfo in allPersonInfos { dataProvider?.addPerson(personInfo/span> in allPersonInfos { dataProvider?.addPerson(personInfo这里举的例子是一个常见的基于TableView的界面——一个通讯录用户信息列表。
我们要实现的业务流程如下 App启动后首先读取本地Core Data中的数据,并展现出来,然后调用Web API来获取到用户数据列表,然后更新本地Core Data数据库,只要数据更新了,UI上的展现也随之变化。 用户也可以在本地添加用户数据,然后这些数据会同步到服务端。 1. 声明协议 我们不会把所有的业务逻辑都写到ViewController里,而是首先声明两个protocol: PeopleListDataProviderProtocol 定义了数据源对象要实现的属性和方法
APICommunicatorProtocol 定义了API请求者要实现的属性和方法
2. 编写ViewController 我们的ViewController叫做PeopleListViewController,在其中声明两个属性:
实现ViewDidLoad
添加按钮的事件响应方法和回调:
然后再添加两个方法来请求和同步数据:
|