<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                > 原文出處: http://chengway.in/post/ji-zhu/core-data-by-tutorials-bi-ji-san 今天繼續來學習Raywenderlich家[《Core Data by Tutorials》](http://www.raywenderlich.com/store/core-data-by-tutorials)的第五章,本章將會聚焦在**NSFetchedResultsController** * * * ## **Chapter 5: NSFetchedResultsController** 作者在開篇就提到了NSFetchedResultsController雖然是一個controller,但是他并不是一個view controller,因為他沒有view。 按本章的目錄梳理一下 ### **一、Introducing the World Cup app** 本章要完成一個World Cup App,作者提供了一個基本的Start Project,快速瀏覽一下,原始數據保存在seed.json文件中。 ### **二、It all begins with a fetch request...** **NSFetchedResultsController**大概是可以看做對“NSFetchRequest獲取結果”這一過程的一種封裝。話不多說,直接上代碼: ~~~ //1 let fetchRequest = NSFetchRequest(entityName: "Team") //2 fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.context, sectionNameKeyPath: nil, cacheName: nil) //3 var error: NSError? = nil if (!fetchedResultsController.performFetch(&error)) { println("Error: \(error?.localizedDescription)") } ~~~ > 前面介紹過,NSFetchRequest是可以高度定制化的,包括sort descriptors、predicates等 注意一下NSFetchedResultsController初始化需要的兩個必要參數fetchRequest和context,第3步由之前的context來performFetch改為NSFetchedResultsController來performFetch,可以看做是NSFetchedResultsController接管了context所做的工作,當然NSFetchedResultsController不僅僅是封裝performFetch,他更重要的使命是負責協調Core Data和Table View顯示之間的同步。這樣一來,你所需要做到工作就只剩下了提供各種定制好的NSFetchRequest給NSFetchedResultsController就好了。 除了封裝了fetch request之外,NSFetchedResultsController內部有容器存儲了fetched回來的結果,可以使用fetchedObjects屬性或objectAtIndexPath方法來獲取到。下面是一些提供的Data source方法: ~~~ func numberOfSectionsInTableView(tableView: UITableView) -> Int { return fetchedResultsController.sections!.count } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { let sectionInfo = fetchedResultsController.sections![section] as NSFetchedResultsSectionInfo return sectionInfo.numberOfObjects } ~~~ sections 數組包含的對象實現了NSFetchedResultsSectionInfo代理,由他來提供title和count信息。接著來看configureCell ~~~ func configureCell(cell: TeamCell, indexPath: NSIndexPath) { let team = fetchedResultsController.objectAtIndexPath(indexPath) as Team cell.flagImageView.image = UIImage(named: team.imageName) cell.teamLabel.text = team.teamName cell.scoreLabel.text = "Wins: \(team.wins)" } ~~~ 這里沒有專門的數組來保存數據,數據都存在fetched results controller中,并通過objectAtIndexPath來獲取。 這里還要注意的一點就是**NSFetchedResultsController至少需要設置一個sort descriptor**,標準的fetch request是不需要的,但NSFetchedResultsController涉及到table view的操作,需要知道列表的排列順序。這樣就可以了,按名稱排序: ~~~ let sortDescriptor = NSSortDescriptor(key: "teamName", ascending: true) fetchRequest.sortDescriptors = [sortDescriptor] ~~~ ### **三、Grouping results into sections** 參加世界杯的有亞、非、歐、大洋洲、南美,中北美及加勒比海等六大洲,球隊需要按歸屬地(qualifyingZone)分類。qualifyingZone是Team實體的一個屬性。用NSFetchedResultsController實現起來相當簡單: ~~~ fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.context, sectionNameKeyPath: "qualifyingZone", cacheName: nil) ~~~ 按sectionNameKeyPath分組,使用起來還是相當靈活的 > sectionNameKeyPath takes a keyPath string. It can take the form of an attribute name such as “qualifyingZone” or “teamName”, or it can drill deep into a Core Data relationship, such as “employee.address.street”. 這里還有一點要特別注意:上面我們將NSSortDescriptor只設為teamName排序,而當使用sectionNameKeyPath為qualifyingZone就會報錯,正確的方法是在剛才設置NSSortDescriptor的地方添加key為qualifyingZone的NSSortDescriptor實例: ~~~ let zoneSort = NSSortDescriptor(key: "qualifyingZone", ascending: true) let scoreSort = NSSortDescriptor(key: "wins", ascending: false) let nameSort = NSSortDescriptor(key: "teamName", ascending: true) fetchRequest.sortDescriptors = [zoneSort, scoreSort, nameSort] ~~~ > If you want to separate fetched results using a section keyPath, the first sort descriptor’s attribute must match the key path’s attribute. > 如果要按section keyPath分組,必須創建一個key為key path的NSSortDescriptor實例,并放在**第一位** 運行一下程序,發現每個分組內的球隊先是按分數排序,然后才會按姓名,這是因為數組內對象的先后順序和排序的優先級是相關的。 ~~~ fetchRequest.sortDescriptors = [zoneSort, scoreSort, nameSort] ~~~ ### **四、“Cache” the ball** 將球隊分組的操作開銷有時候并不小,32支球隊或許不算什么,但上百萬的數據呢,或許你會想到丟掉后臺去操作,這樣確實不會阻塞主線程UI,但分組在后臺還是會花上很長時間,你還是要loading好久才能有結果,如果每次fetch都這樣,的確是個頭疼的問題。好的解決辦法就是,只付出一次代價,之后每次可以重用這個結果。NSFetchedResultsController的作者已經想到這個問題了,為我們提供了cahing來解決,打開它就好了。 ~~~ fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: coreDataStack.context, sectionNameKeyPath: "qualifyingZone", cacheName: "worldCup") ~~~ 要特別記住的就是這里的**section cache**?與Core Data中的*persistent store*是完全獨立的 > NSFetchedResultsController’s section cache is very sensitive to changes in its fetch request. As you can imagine, any changes—such as a different entity description or different sort descriptors—would give you a completely different set of fetched objects, invalidating the cache completely. If you make changes like this, you must delete the existing cache using deleteCacheWithName: or use a different cache name. > section cache其實相當易變,要時刻注意 ### **五、Monitoring changes** 最后一個特性,十分強大但容易被濫用,也被作者稱為是雙刃劍。首先NSFetchedResultsController可以監聽result set中變化,并且通知他的delegate。你只需要使用他的delegate方法來刷新tableView就ok了。 > A fetched results controller can only monitor changes made via the managed object context specified in its initializer. If you create a separate NSManagedObjectContext somewhere else in your app and start making changes there, your delegate method won’t run until those changes have been saved and merged with the fetched results controller’s context. > 說白了就是只能監聽NSFetchedResultsController初始化傳進來的context中的changes,其他不相關的context是監聽不到的,除非合并到這個context中,這個在多線程中會用到。 下面是一個通常的用法 ~~~ func controllerWillChangeContent(controller: NSFetchedResultsController!) { tableView.beginUpdates() } func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath!, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath!) { switch type { case .Insert: tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Automatic) case .Delete: tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) case .Update: let cell = tableView.cellForRowAtIndexPath(indexPath) as TeamCell configureCell(cell, indexPath: indexPath) case .Move: tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Automatic) default: break } } func controllerDidChangeContent(controller: NSFetchedResultsController!) { tableView.endUpdates() } ~~~ 這個代理方法會被反復調用,無論data怎么變,tableView始終與persistent store保持一致。 ### **六、Inserting an underdog** 最后作者開了個小玩笑,搖動手機可以走后門加一支球隊進來(比如中國隊?)。其實完全是為了展示Monitoring changes的強大~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看