2014-10-22 72 views
0

我仍然在努力處理核心數據堆棧中傳遞對象的最佳方法。如何我開始供參考:繞過核心數據堆棧傳遞

  1. 應用是超級簡單,單線程的核心數據訪問是完美的,只有少數的意見和各需要一個MOC。以創建Core Data Stack和一個MOC的示例代碼開始。 MOC存儲在App Delegate中。

  2. 應用程序開始變得越來越複雜,並最終意識到爲什麼在App Delegate中存儲MOC是一個糟糕的主意。重構的代碼在App Delegate中創建MOC,並將MOC注入根視圖控制器。從那裏開始,App Delegate沒有保留MOC,並且視圖控制器將其注入到可能需要它的其他控制器中。

  3. 開始重構故事板中的應用程序視圖。新的標籤欄,一些導航控制器,分割視圖控制器,你只知道一些不同的想法。步驟#2變成了一場噩夢。每當我對故事板中的應用程序視圖層次進行更改時,我都需要重新調整每個視圖控制器,以通過新層次結構傳遞MOC。當然,蘋果說這是正確的方式,但我不確定我是否購買它,非常難以在不殺死代碼的情況下進行簡單的視圖層級更改。現在我在我的應用程序的開頭有4個視圖,甚至不需要MOC。然而,這些視圖是應用程序委託人與需要MOC的視圖控制器的唯一鏈接。所以我被卡住注入MOC到所有這些視圖控制器中,以便它們可以將它傳遞給另一個視圖控制器,而無需每次使用MOC。

  4. 應用程序更加複雜,現在我想要一個線程化的核心數據堆棧。這意味着要傳遞持久性存儲,以便某些「處理」對象可以在後臺線程上創建自己的MOC。我應該創建一些可以幫助管理器的CoreDataStack對象嗎? I.E.的對象,我可以要求主線程MOC,或要求一個新的'工人'背景MOC。看起來像現在第3步更加毫無意義,我的意思是我的應用程序中的每個視圖都需要訪問主線程MOC,而不是其他任何東西。我想我沒有看到這一個改變了一段時間,但誰知道我已經改變了很多,因爲我開始;)

我覺得「CoreDataStack」對象可以管理分佈的想法MOC可能是一個好主意。這樣,至少該對象可以抽象出我選擇實現線程堆棧的方式的實現細節。 I.E.提供方法來掏出主要的MOC和背景MOC。

這似乎很好,直到我開始考慮如何傳遞這個堆棧對象。我可以做到蘋果推薦的內容,並將其從控制器傳遞到控制器,將主線程MOC注入到每個視圖控制器中。但正如我上面所說的,在故事板上重新工作大約5分鐘,這使得這種情況迅速崩潰。更不用說將MOC傳遞給並不真正需要的視圖,以便它們可以傳遞到層次結構中可能需要它的下一個視圖。

最後我的問題。是否有更好的解決方案,而不是傳遞/注入MOC到每個視圖控制器?

+0

使用核心數據和多線程環境中的對象可能會非常複雜。看看Magical Record,它會消除很多痛苦。 https://github.com/magicalpanda/MagicalRecord – sbarow 2014-10-22 05:00:28

+0

2是首選方式,特別是在使用嵌套上下文時。通過使用非正式協議,您可以使您的實施更輕鬆。如果遵循規則併爲不同的工作機構創建新的上下文,併發不應該引入問題。 http://quellish.tumblr.com/post/97430076027/a-real-guide-to-core-data-concurrency – quellish 2014-10-23 02:12:58

回答

-2

我使用的一種新技術是代理對象。基本上我所做的是製作一個模仿管理對象的struct。對於所有讀取操作,我使用這個模擬對象。如果用戶正在編輯數據但尚未「保存」,我也使用模擬對象。只有當用戶承諾保存對象時,我才使用Core Data。在這一點上,我呼籲其在這裏創建了MOC單,

// My `AppDelegate` conforms to `UIApplicationDelegateWithPSC` 
protocol UIApplicationDelegateWithPSC { 

    func providePersistentStoreCoordinator() -> NSPersistentStoreCoordinator 

} 

class ContextManager { 

    static let sharedInstance = ContextManager(concurrencyType: .mainQueueConcurrencyType) 

    private init(concurrencyType: NSManagedObjectContextConcurrencyType) { } 

    lazy var context: NSManagedObjectContext = { 
     return { 
     let modelURL = Bundle.main.url(forResource: "Foo", withExtension: "momd") 
     let mom = NSManagedObjectModel(contentsOf: modelURL!) 
     let appDelegateWithPSC = UIApplication.shared.delegate as! UIApplicationDelegateWithPSC 
     let psc = appDelegateWithPSC.providePersistentStoreCoordinator() 
     let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 
     let storeURL = (urls[urls.endIndex-1]).appendingPathComponent("Bar") 
     var error: NSError? = nil 
     var store: NSPersistentStore? 
     do { 
      store = try psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: storeURL, options: nil) 
     } catch let error1 as NSError { 
      error = error1 
      store = nil 
     } catch { 
      fatalError() 
     } 
     let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) 
     managedObjectContext.persistentStoreCoordinator = psc 

     return managedObjectContext 
     }() 
    }() 

} 

我呼籲的背景如下:

 ContextManager.sharedInstance.context.performAndWait({ 
     do { 
      let foo = NSEntityDescription.insertNewObject(forEntityName: "Foo", into: ContextManager.sharedInstance.context) as? Foo 
      // `mimicStruct` is the struct i've been using to avoid the headaches of complying with rules for manipulating ManagedObjects. 
      foo?.name = mimicStruct.name 
      try ContextManager.sharedInstance.context.save() 

     } catch { 

     } 
    }) 

通過使用單獨的對象爲我的背景,我避免了複雜性多線程代碼。請注意,我也使這是一個performAndWait,這意味着我阻止,但由於我只在讀取/寫入數據庫時​​執行此操作,因此用戶通常會期待稍微暫停,而微調器指示Loading...Saving...。我最終減少了對MOC的訪問次數,並避免了很多複雜性。

+0

我需要的不僅僅是id,即tableviews等整個上下文。 Ids和MOC仍然在不同的地方傳遞着同樣的信息,它改變了故事情節,並重新進行了大規模的代碼更新。 – lostintranslation 2014-10-22 14:35:16

+0

爲了澄清,WWDC 2014會議@Vader提到了關於核心數據併發模型歷史的討論,而不是如何自行傳遞上下文的歷史。 – quellish 2014-10-23 02:17:06

1

你說

應用開始變得更加複雜,終於實現了,爲什麼存儲在App代表的MOC是一個壞主意。

你對這件事究竟有什麼不滿?對於你提到的應用程序委託或單例的問題是非常合適的解決方案。我只想從所有控制器刪除應用程序委託代碼

  • 不需要核心數據
  • 有一個對象作爲伊娃(你可以從被管理對象的子類被管理對象上下文)

除非您有大量記錄並需要提取結果控制器,否則您可以僅使用沒有提取請求的對象圖,因此核心數據層很好地「抽象出」。