GitHub&CoreData(以下简称GC)项目是一个可以实时从GitHub的swift‘s Project里抓取更新的App。
其中用到了第三方的json库SwiftyJSON,以及用来保存,枚举以及修改数据的NSFetchedResultsController对象。
但是该项目在实际运行时用NSFetchedResultsController分组显示的内容却是乱的,相关初始化代码如下:
let fetch = NSFetchRequest<Commit>(entityName:"Commit")
let sortDate = NSSortDescriptor(key: "date", ascending: false)
fetch.sortDescriptors = [sortDate]
fetch.fetchBatchSize = 20
fetchResultsController = NSFetchedResultsController(fetchRequest: fetch, managedObjectContext: managedObjectContext, sectionNameKeyPath: "author.name", cacheName: nil)
fetchResultsController.delegate = self
此时的运行结果如下:
可以看到我以commit的作者分组,但是实际每组的元素是乱序的,根本不是以author来分布的!
那么错误在哪里呢!?原因就在于我们初始化NSFetchRequest的时候选择的排序关键字不正确,如果你要在NSFetchedResultsController启用分组,那么第一个排序关键字必须与实际分组的关键字一致,然后在用第二排序关键再排序每组内的元素。
将之前初始化代码修改如下:
let fetch = NSFetchRequest<Commit>(entityName:"Commit")
let sortDate = NSSortDescriptor(key: "date", ascending: false)
let sortName = NSSortDescriptor(key: "author.name", ascending: false)
fetch.sortDescriptors = [sortName,sortDate]
fetch.fetchBatchSize = 20
fetchResultsController = NSFetchedResultsController(fetchRequest: fetch, managedObjectContext: managedObjectContext, sectionNameKeyPath: "author.name", cacheName: nil)
fetchResultsController.delegate = self
再看一下运行结果:
这下OK了!
接下来GC项目里有一块未完成的部分,即在用户点击列表视图中的一个commit时,会切换至详细视图,在导航栏的右上角的显示与该commit相同author 的所有commits按钮的功能并未完成:
这个很好办!因为该导航栏按钮时动态生成的所以我们只得用代码动态生成所有界面,否则直接在IB中创建VC也是很方便的。
创建一个新的AuthorCommitsTableViewController类,派生自UITableViewController;添加2个属性:
var author:Author!
var commits:[Commit]!
分别表示与该VC相关的author和该author下的所有commits,将该VC的初始化方法修改为如下代码:
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
commits = author.commits.allObjects as! [Commit]
}
然后补全齐TableView的相关代码:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let commit = commits[indexPath.row]
cell.textLabel?.text = "\(commit.author.name): \(commits[indexPath.row].message)"
return cell
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return commits.count
}
再回到DetailViewController.swift中添加如下方法:
func showAuthorCommits(){
let authorCommitsVC = AuthorCommitsTableViewController()
authorCommitsVC.author = detailItem?.author
navigationController?.pushViewController(authorCommitsVC, animated: true)
}
我们用短短几行代码已经完成了所需要的功能: