objective-c 電腦每次所能存取硬碟的最小區域為 - 每個核心數據關係都必須有一個逆向嗎?




下列哪些屬於電子商務的應用1電子拍賣2電子化政府3代客泊車4協同商務 (6)

假設我有兩個實體類: SocialAppSocialAppType

SocialApp我有一個屬性: appURL和一個關係: type

SocialAppType我有三個屬性: baseURLnamefavicon

SocialApp關係type的目標是SocialApp中的單個記錄。

舉例來說,對於多個Flickr賬戶,將會有一些SocialApp記錄,每個記錄都持有一個到一個人賬戶的鏈接。 對於“Flickr”類型將有一個SocialAppType記錄,即所有SocialApp記錄都會指向該記錄。

當我使用該模式構建應用程序時,我得到一個警告,即SocialAppTypeSocialApp之間沒有反向關係。

 /Users/username/Developer/objc/TestApp/TestApp.xcdatamodel:SocialApp.type: warning: SocialApp.type -- relationship does not have an inverse

我需要反過來,為什麼?


Answers

至少有一種情況可以在核心數據關係沒有逆轉的情況下進行良好處理:當兩個對象之間存在另一個核心數據關係時,它將處理維護對像圖。

例如,一本書包含許多頁面,而一頁則放在一本書中。 這是一種雙向多對一的關係。 刪除一個頁面只會使關係無效,而刪除一本書也會刪除該頁面。

但是,您也可能希望跟踪每本書正在閱讀的當前頁面。 這可以通過頁面上的“currentPage” 屬性完成,但您需要其他邏輯來確保書中只有一個頁面隨時被標記為當前頁面。 相反,將Book從當前頁面關係中創建為單個頁面將確保始終只有一個當前頁面被標記,並且此頁面只需book.currentPage即可輕鬆訪問該書籍。

在這種情況下,互惠關係會是什麼? 有些東西很無意義。 “myBook”或類似文件可以在其他方向上添加,但它只包含頁面“book”關係中已包含的信息,因此會產生自己的風險。 也許在將來,您使用這些關係之一的方式會發生變化,導致您的核心數據配置發生變化。 如果page.myBook已經在代碼中使用page.book的某些地方使用過,則可能會出現問題。 主動避免這種情況的另一種方法是,不要在用於訪問頁面的NSManagedObject子類中公開myBook。 然而,可以認為,首先不對倒數建模是比較簡單的。

在上面的示例中,當前頁面關係的刪除規則應設置為“無操作”或“級聯”,因為與“無效”沒有相互關係。 (Cascade意味著你在閱讀書的時候將書中的每一頁都撕掉了,但是如果你特別冷,並且需要燃料,這可能是真的。)

如果可以證明對像圖完整性沒有風險,如本例中所示,並且代碼複雜性和可維護性得到改進,那麼可以認為沒有相反的關係可能​​是正確的決定。


雖然文檔似乎並不需要反過來,但我只是解決了一個實際上由於沒有反轉而導致“數據丟失”的場景。 我有一個在可報告對像上具有多對多關係的報表對象。 如果沒有相反的關係,重新啟動時,對多關係的任何更改都會丟失。 在檢查Core Data調試之後,顯然即使我保存了報表對象,對像圖(關係)的更新也從未進行過。 我加了一個反過來,即使我不使用它,瞧,它的工作原理。 所以它可能不會說這是必需的,但沒有反向的關係肯定會有奇怪的副作用。


更好的問題是,“是否有理由反過來”? 核心數據實際上是一個對像圖管理框架,而不是一個持久性框架。 換句話說,它的工作是管理對像圖中對象之間的關係。 逆關係使得這容易。 出於這個原因,核心數據需要反向關係,並為該用例編寫。 沒有它們,你將不得不自己管理對像圖的一致性。 特別是,沒有反向關係的多對多關係很可能會被Core Data破壞,除非您努力工作以保持工作。 對於反向關係而言,磁盤大小的成本與獲得的收益相比確實微不足道。


我將解釋Dave Mark和Jeff LeMarche在“ 更多iPhone 3開發”中找到的權威答案。

Apple通常建議您始終創建並指定反轉,即使您未在應用中使用反轉關係。 出於這個原因,當你不能提供反向時,它會警告你。

關係不需要有相反的關係,因為有幾種情況,反向關係可能會影響績效。 例如,假設反比關係包含非常大量的對象。 去除反函數需要遍歷表示反轉弱性能的集合。

但是除非你有一個特定的原因不去模擬逆過程 。 它有助於核心數據確保數據完整性。 如果遇到性能問題,稍後刪除反向關係相對容易。


蘋果的文檔有一個很好的例子,表明你可能因沒有反向關係而出現問題。 讓我們將其映射到這種情況。

假設您按如下方式對其進行建模:

請注意,您有一個從SocialAppSocialAppType稱為“ type的一對一關係。 該關係是非可選的並且具有“拒絕”刪除規則

現在考慮以下幾點:

SocialApp *socialApp;
SocialAppType *appType;
// assume entity instances correctly instantiated

[socialApp setSocialAppType:appType];
[managedObjectContext deleteObject:appType];
BOOL saved = [managedObjectContext save:&error];

我們期望的是會失敗此上下文保存,因為我們已將刪除規則設置為拒絕,而關係不是可選的。

但是這裡保存成功。

原因是我們沒有設定反比關係 。 因此,當appType被刪除時,socialApp實例不會被標記為已更改。 因此,在保存之前沒有對socialApp進行驗證(它假定沒有需要驗證,因為沒有發生變化)。 但實際上發生了變化。 但它沒有得到體現。

如果我們回想一下appType

SocialAppType *appType = [socialApp socialAppType];

appType是零。

奇怪,不是嗎? 對於非可選屬性,我們得到零嗎?

所以,如果你建立了反向關係,你就沒有麻煩了。 否則,您必須通過編寫代碼進行強制驗證,如下所示。

SocialApp *socialApp;
SocialAppType *appType;
// assume entity instances correctly instantiated

[socialApp setSocialAppType:appType];
[managedObjectContext deleteObject:appType];

[socialApp setValue:nil forKey:@"socialAppType"]
BOOL saved = [managedObjectContext save:&error];

這個問題沒有一個正確的答案,但這是我接近它的方法:

守護程序和查看器應用程序都使用相同的核心數據存儲來保存和檢索數據。

因為不支持在進程之間共享Core Data存儲(據我所知),我將讓守護進程公開XPC服務 。 查看器將使用NSXPCConnection通過守護程序訪問數據,而不是打開Core Data存儲本身。

假設查看器從未在沒有守護進程的情況下運行,它可以使用SMLoginItemSetEnabled (如問題中提到的那樣)為守護進程註冊mach服務,然後連接到該服務。

這裡有一些示例代碼,詳細介紹了在Apple網站上設置的內容(摘要:守護程序需要位於App.app/Contents/Library/LoginItems/daemon.bundle.id.app ),您可能還想閱讀此博客文章 ,討論沙盒強加的一些額外要求(摘要:請確保您的團隊ID在守護程序的捆綁標識符中)。

守護程序應始終在查看器啟動時啟動。

全部設置:一旦您使用SMLoginItemSetEnabled註冊守護程序,當觀察者連接到其XPC服務時,launchd將啟動它(如果需要)。

現在,當用戶退出守護程序時,查看器也應該停止。

查看器可以使用NSXPCConnection來查找守護進程何時退出。 守護進程也可以在退出之前使用SMLoginItemSetEnabled取消註冊,這樣它就不會重新啟動。

我想使用NSUserDefaults進行基本配置,我能以某種方式在守護進程和查看器之間交換這些數據嗎? 同樣,兩個應用程序將具有不同的包標識符。

使用套件:

// To read or write:
NSUserDefaults* suiteDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"com.example.app.shared"];
[suiteDefaults setObject:[NSDate date] forKey:@"launchTime"];

// Add the suite to -standardUserDefaults to make reading easier:
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults addSuiteNamed:@"com.example.app.shared"];

要使用沙盒,查看器和守護程序必須共享應用程序組。 您甚至可以使用KVO觀察共享密鑰的更改。





objective-c core-data