<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-er 今天繼續來重溫Raywenderlich家的[《Core Data by Tutorials》](http://www.raywenderlich.com/store/core-data-by-tutorials)。學完前三章就掌握了CoreData的基本知識,現在我們來深入來研究下Fetching? * * * ## **Chapter 4: Intermediate Fetching** 這一章主要深入地探究Fetching,學完這一章,你將會加滿如下技能點: * fetch only what you need to; * refine your fetched results using predicates; * fetch in the background to avoid blocking the UI; * avoid unnecessary fetching by updating objects directly in the persistent store. 還是按作者的主要目錄來梳理一下吧: ### **一、NSFetchRequest: the star of the show** 明星登場,同樣是創建NSFetchRequest的實例,并對其進行configure且執行。總而言之,繁重的工作都替你干了,任勞任怨的程度和NSManagedObjectContext有一拼。接著展示了四種創建NSFetchRequest實例的方式: ~~~ //1 let fetchRequest1 = NSFetchRequest() let entity = NSEntityDescription.entityForName("Person", inManagedObjectContext: managedObjectContext!) let entity = NSEntityDescription.entityForName("Person", inManagedObjectContext: managedObjectContext!) //2 let fetchRequest2 = NSFetchRequest(entityName: "Person") //3 let fetchRequest3 = managedObjectModel.fetchRequestTemplateForName("peopleFR") //4 let fetchRequest4 = managedObjectModel.fetchRequestFromTemplateWithName("peopleFR", substitutionVariables: ["NAME" : "Ray"]) ~~~ ### **二、Introducing the Bubble Tea app** 本章要實現一個泡泡?茶的APP,作者提供了一個Start project,快速瀏覽一下,主界面是一個TableView,奶茶店等原始數據都保存seed.json之中。接下來要考慮如何將數據從seed中讀取到Core Data的對象中去。 ### **三、Stored fetch requests** 這里可以在data model中設置一個Fetch Request,并選擇Fetch哪些對象,設置一些條件;緊接著你就可以使用模板中fetchRequest了: ~~~ fetchRequest = coreDataStack.model.fetchRequestTemplateForName("FetchRequest") ~~~ 這里要使用coreData,并注意FetchRequest名稱要和model中的匹配。 ### **四、Fetching different result types** 作者把NSFetchRequest比喻成了Core Data framework中的瑞士軍刀,看來還是相當強大的。這里有四種fetch request的result type: ~~~ ①.NSManagedObjectResultType: Returns managed objects (default value). ②.NSCountResultType: Returns the count of the objects that match the fetch request. ③.NSDictionaryResultType: This is a catch-all return type for returning the results of different calculations. ④.NSManagedObjectIDResultType: Returns unique identifiers instead of full- fledged managed objects. ~~~ 將**fetchRequest.resultType**設為**NSCountResultType**在查詢大量對象數量時可以極大的優化性能。 另一種獲取count的方式是context直接調用**countForFetchRequest**方法 ~~~ let count = coreDataStack.context.countForFetchRequest(fetchRequest, error: &error) ~~~ Core Data提供了多種函數支持來支持計算,如average, sum, min and max. 下面是一個求和的例子: ~~~ func populateDealsCountLabel() { //1 指定result類型 let fetchRequest = NSFetchRequest(entityName: "Venue") fetchRequest.resultType = .DictionaryResultType //2 創建表達式描述,指定個名稱,以便將來在fetch的結果(字典類型)中找到 let sumExpressionDesc = NSExpressionDescription() sumExpressionDesc.name = "sumDeals" //3 創建具體的表達式 sumExpressionDesc.expression = NSExpression(forFunction: "sum:", arguments:[NSExpression(forKeyPath: "specialCount")]) sumExpressionDesc.expressionResultType = .Integer32AttributeType //4 設置fetch request 將要fetch sum fetchRequest.propertiesToFetch = [sumExpressionDesc] //5 執行,最后通過之前設置的表達式name得到最終結果 var error: NSError? let result = coreDataStack.context.executeFetchRequest(fetchRequest, error: &error) as [NSDictionary]? if let resultArray = result { let resultDict = resultArray[0] let numDeals: AnyObject? = resultDict["sumDeals"] numDealsLabel.text = "\(numDeals!) total deals" } else { println("Could not fetch \(error), \(error!.userInfo)") } } ~~~ 現在還剩一種.ManagedObjectIDResultType類型,他返回一個包含NSManagedObjectID對象的數組,NSManagedObjectID 可以看成是managed object通用唯一標識,除了多線程的某些場景下,否則很少用到它。 關于性能優化CoreData通過以下幾種方式來削減income data: ~~~ ①.fetch batches,可以使用fetchBatchSize, fetchLimit 和 fetchOffset這些屬性來削減income data。 ②.支持**faulting**這樣的*占位符*。 ③.使用predicates ~~~ 最后要注意一下如果想要在運行時改變predicate,就不能再用model來初始化fetchRequest了 ~~~ override func viewDidLoad() { super.viewDidLoad() // fetchRequest = coreDataStack.model.fetchRequestTemplateForName("FetchRequest") fetchRequest = NSFetchRequest(entityName: "Venue") fetchAndReload() } ~~~ 至于predicates的用法請查看[官方文檔](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html) ### **五、Sorting fetched results** 排序主要用到了NSSortDescriptor這個類,值得注意的是該排序是真正發生在**SQLite層面**的,而不是在內存中的,因此該排序十分高效。 NSSortDescriptor實例初始化需要三個參數:①.你要排序屬性的key path ②.指明升序 or 降序 ③. 一個可選的selector 這里要注意一點就是CoreData不支持block-based API定義NSSortDescriptor,以及基于block-based方式定義NSPredicate。 ~~~ //下面兩個初始化方法不能用于CoreData中 + (instancetype)sortDescriptorWithKey:(NSString *)key ascending:(BOOL)ascending comparator:(NSComparator)cmptr + (NSPredicate *)predicateWithBlock:(BOOL (^)(id evaluatedObject, NSDictionary *bindings))block ~~~ 下面創建了一個按名字排序**filter** ~~~ lazy var nameSortDescriptor: NSSortDescriptor = { var sd = NSSortDescriptor(key: "name", ascending: true, selector: "localizedStandardCompare:") return sd }() ~~~ 這里注意一下第三個參數*localizedStandardCompare*,傳入這個參數就會按本地語言排序,這也是蘋果官方推薦的一種做法。 得到一個反轉排序的sortDescriptor也很簡單,這樣就可以了 ~~~ selectedSortDescriptor = nameSortDescriptor.reversedSortDescriptor ~~~ ### **六、Asynchronous fetching** iOS 8蘋果推出全新的API來處理異步fetch問題,**NSAsynchronousFetchRequest**,這里不要被他的名字迷惑了,和NSFetchRequest沒什么直接關系,他其實是**NSPersistentStoreRequest**的子類。下面是該類的定義及初始化方法: ~~~ @availability(iOS, introduced=8.0) class NSAsynchronousFetchRequest : NSPersistentStoreRequest { var fetchRequest: NSFetchRequest { get } var completionBlock: NSPersistentStoreAsynchronousFetchResultCompletionBlock? { get } var estimatedResultCount: Int init(fetchRequest request: NSFetchRequest, completionBlock blk: NSPersistentStoreAsynchronousFetchResultCompletionBlock?) } ~~~ 從該類的初始化方法可以將*異步fetchRequest*看做是對fetchRequest的一種包裝,第一個參數是標準的NSFetchRequest 對象,而第二個參數是一個**a completion handler**,不過僅僅有completion handler是不夠的,最后還是需要*executeRequest*,下面是一個完整的例子: ~~~ //1 fetchRequest = NSFetchRequest(entityName: "Venue") //2 asyncFetchRequest = NSAsynchronousFetchRequest(fetchRequest: fetchRequest) { [unowned self] (result: NSAsynchronousFetchResult! ) -> Void in self.venues = result.finalResult as [Venue] self.tableView.reloadData() } //3 var error: NSError? let results = coreDataStack.context.executeRequest(asyncFetchRequest, error: &error) if let persistentStoreResults = results { //Returns immediately, cancel here if you want } else { println("Could not fetch \(error), \(error!.userInfo)") } ~~~ 這段代碼注意executeRequest一旦執行立即返回一個*NSAsynchronousFetchResult*類型的結果,在這里你不用操心fetch到的數據和UI匹配,這些工作都在第二步handle那里處理了。另外NSAsynchronousFetchResult是有cancel()方法的。 僅僅有新API還不夠,還要修改context ~~~ context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) ~~~ > 另外一種*.PrivateQueueConcurrencyType*將在后面多線程介紹 因為是異步fetch,所以可能tableview初始化完畢后,fetch的結果才到,這里給數據源可以設置一個空數組來fix。 ### **七、Batch updates: no fetching required** 有的時候你需要一次更新很多屬性,全部fetch到內存顯然是不高效的,iOS 8推出了全新的批量更新(batch updates)來解決這一痛點。這個類就是**NSBatchUpdateRequest**,和上面提到的*NSAsynchronousFetchRequest*都是**NSPersistentStoreRequest**的子類,下面是這個類的定義: ~~~ @availability(iOS, introduced=8.0) class NSBatchUpdateRequest : NSPersistentStoreRequest { init(entityName: String) init(entity: NSEntityDescription) var entityName: String { get } var entity: NSEntityDescription { get } var predicate: NSPredicate? // Should the update include subentities? Defaults to YES. var includesSubentities: Bool // The type of result that should be returned from this request. Defaults to NSStatusOnlyResultType var resultType: NSBatchUpdateRequestResultType // Dictionary of NSPropertyDescription|property name string -> constantValue/NSExpression pairs describing the desired updates. // The expressions can be any NSExpression that evaluates to a scalar value. var propertiesToUpdate: [NSObject : AnyObject]? } ~~~ 具體使用起來也很簡單: ~~~ let batchUpdate = NSBatchUpdateRequest(entityName: "Venue") batchUpdate.propertiesToUpdate = ["favorite" : NSNumber(bool: true)] batchUpdate.affectedStores = coreDataStack.psc.persistentStores batchUpdate.resultType = .UpdatedObjectsCountResultType var batchError: NSError? let batchResult = coreDataStack.context.executeRequest(batchUpdate, error: &batchError) as NSBatchUpdateResult? if let result = batchResult { println("Records updated \(result.result!)") } else { println("Could not update \(batchError), \(batchError!.userInfo)") } ~~~ 最后注意一點,就是批量更新跳過了NSManagedObjectContext,直接對persistentStore進行更新,沒有經過有效性驗證,這個就要靠你自己確保更新的數據合法了。
                  <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>

                              哎呀哎呀视频在线观看