2012-05-01 44 views
3

所以我與核心數據掙扎。我發現有很多方法可以做同樣的事情,而且,如果你試圖建立使用故事板,你需要閱讀所有的教程,比去年年長配有翻譯片的例子UIManagedDocuments應用。今天的問題是關於在添加新的託管對象時尋找最佳實踐。我見過的例子這兩種方式:在Core Data中創建新對象:先創建還是返回?

  1. 創建一個表視圖控制器,新的管理對象,並賦予新的閃耀管理對象的下級(點擊+後)「添加」視圖控制器獲取用戶輸入爲所有的對象屬性。這看起來很簡單,返回的對象很容易理解,因爲它包含所有的單個屬性。但我見過的示例代碼中的「取消」按鈕刪除傳入的管理對象這一「添加」視圖控制器,然後解僱本身之前調用保存上下文。功能,但在我的肩膀上的MVC培訓侏儒在我尖叫有這個下屬添加視圖刪除對象和恐怖直接調用保存上下文。來自Apple的配方示例代碼似乎使用此方法。

  2. 發送沒什麼可添加視圖控制器,並將它發回的委託調用返回的各個屬性作爲一個單獨傳遞的參數的表視圖控制器。所以返回方法變得非常長:controller:(UIViewController *)controller didReturnFirstName:(NSString *)firstName andLastName:(NSString *)lastName andStreetAddress:(NSString *)and ... and ... and ..但是這是SO與MVC教條一致,因爲託管對象在接收到所有單個屬性時會在表視圖控制器中創建,並且「添加」視圖永遠不會觸及模型(核心數據),或者在用戶更改時丟棄未使用的託管對象他們的頭腦。
    即使鏈式委託方法,我還在與自己爭論這是一個更好的方法。來自那些與這兩種形式生活的人的評論和想法將是一個受歡迎的補充。

謝謝。

+0

我認爲數據模型可以將1個託管對象發送給視圖控制器來顯示。例如,您的聯繫人。當您查看一個聯繫人時,我不希望保存的數據模型將每個字段單獨傳遞給視圖控制器,而是傳遞一個管理對象,該對象聯繫該聯繫人的所有信息。對於刪除一個對象,也許把它作爲視圖控制器的目標動作,然後讓視圖控制器消息的數據類刪除該對象... – Nick

+0

謝謝,尼克。我同意發送一個對象到視圖控制器來顯示是一致的和堅實的策略。我正在詢問創建過程,您需要(可能)將一個新項目添加到數據庫。您是否在準備segue方法中創建新的託管對象並將其傳遞給新控制器,或者等待並在下級視圖返回後創建新對象? – Unsure1

+0

+1這個問題完全是我想問的問題,而且還有一些基本的東西,它應該放在蘋果文檔或任意數量的教程中。 – Rhubarb

回答

0

我認爲正確的做法實際上是爲您的AddController(如果要創建新項目)或EditController(如果要修改現有項目)創建一個新的獨立NSManagedObjectContext

之所以選擇A)或B)根據您的SDK:

A),然後你有選擇,要麼保存更改在這種情況下,還是放棄上下文。

在「保存」的情況下,您可以合併通過通知(NSManagedObjectDidSaveNotification)將表更改到TableController的ManagedObjectContext

在「取消」,可以只丟棄單獨的上下文。

B的情況下)或者,如果你在OSX 10.7(+),則可以使用嵌套NSManagedObjectContext S,創建以NSManagedObjectContext AddController(子上下文),並設置它的parentContext到TableController的NSManagedObjectContext

在的情況下,「保存」,你會救孩子上下文,父上下文。

在的情況下「取消「,你只需要放棄子上下文。

見這在蘋果的CoreDataBooks例如http://developer.apple.com/library/ios/#samplecode/CoreDataBooks/Introduction/Intro.html

1

它,你看看蘋果的tutorial的例子一個詳細的例子,他們通過做一些下面列出的東西,在這種情況下完成這一任務,他們有一個模式的看法出現輸入將被添加到數據模型中的信息:

  1. 在出現的模態的視圖,它們創建一個協議,以處理任何駁回視圖或保存數據和類型ID的屬性,該屬性實現該協議是delagate,這保證了什麼對象,它是implments所需的方法

  2. 在創建該模態視圖視圖控制器,它們實現的協議,包括保存對象到數據模型和駁回模態視圖

  3. 在視圖控制器創建的模式,他們設置創建的模式視圖模式視圖委託塞克期間模態

因此,要總結,在模態視圖來收集你需要新的數據視圖控制器: 在.h和中創建協議和屬性合成它

@protocol yourProtocol <NSObject>; 
//methods that determine what happens based on what user does, it would save your core data object 
@end 

@property(nonatomic, weak) id<yourProtocol> delegate; 

然後,在模態視圖.m文件,你可能調用這些方法的代表,有可能當他們挑選保存或完成,因此一個方法爲每個連接到一個按鈕

[self.delegate myMethod]; 
IBAction爲

在此提出的模態視圖來看,要實現在.h文件協議

@interface viewController() <yourProtocol> 

最後,添加方法,所呈現的模態視圖控制器視圖的.m文件,這應該包括刪除視圖並保存核心數據。根據蘋果和其他消息來源,導致彈出窗口/模式等的視圖控制器應該是解散它的視圖控制器。然後,在使用seque indentfying的seque中,將在模態視圖中呈現的視圖控制器設置爲模態視圖的代表。

+0

尼克 - 我不知道你和我說話的原因經過彼此。我同意你所說的一切。教程代碼僅收集2條用戶數據(鳥的名稱和位置),因此將這兩條信息從模態視圖傳遞迴代表很簡單。但是我期望擴展數據輸入的字段數量,並認爲委託方法有10個或更多獨立傳遞參數時會變得很麻煩。 – Unsure1

+0

是的,我所說的只是通過包含所有10個參數的「鳥對象」。 – Nick

+0

Ahhhh ...謝謝。我正在重寫代碼來做到這一點。再次感謝您的評論。我很感激他們。 – Unsure1

1

你是對的,有很多方法可以採取這一個。

聽起來好像你已經開始與可能無法保存上下文,所以爲了能夠返回到您的出發點我想解決這樣的:通過創建

  1. 開始新的NSManagedObject被用作臨時對象,它被傳遞給你的「編輯」視圖。
  2. 如果您正在編輯現有對象,請將現有對象中的屬性複製到此新的臨時對象中(您可以使用快速for循環將它們全部複製)。否則,繼續使用新創建的對象。
  3. 將臨時對象傳遞給「編輯」視圖控制器,並讓它處理兩個情況相同。
    a。如果用戶按下取消,則可以使用通知tableview和tableview的協議或委託方法,然後簡單地丟棄臨時對象。 b。如果他們按下save,則通知tableview,然後將臨時副本中的屬性複製回原始並刪除臨時對象(如果它是編輯操作),或者將它保留爲新創建的對象(如果它是「Add 「操作。
0

這不是一個真正的答案,所以可以自由地忽略,但其他任何(迄今)都不是一個完整的答案,我覺得需要添加一些點而不會創建新的問題,因爲我真的想要深入瞭解這一點。尤其答案應該處理

  • 當你取消VS保存會發生什麼
  • 什麼,如果你想使用相同的控制器用於編輯現有的實體,而不是創建一個新的

尼克斯回答處理蘋果(當前)傳遞數據的約定,但不是完整的答案,因爲該教程不處理核心數據管理的對象,並且蘋果自己的樣本使用管理對象以不同方式執行。

但在這個問題上,我發現代表大會是在某些情況下笨拙,很高興從經驗的開發人員閱讀: http://robsprogramknowledge.blogspot.pt/2012/05/back-segues.html

羅布詳細介紹不同的機制,即它們是都同樣有效(包括協議/委託約定(Nick's)),使用沒有協議的數據對象(所謂的「共享內存」) - 更像其他人建議的那樣,以及 - 我最喜歡的 - 使用塊。 塊是一個不錯的選擇,因爲儘管它像代理一樣工作,但代碼仍然完全位於「父」視圖控制器源中的上下文中。但是,「共享內存」更有意義,因爲如您所說,使用除了數據(管理)對象之外的任何東西,你已經設計了來傳遞所有這些屬性看起來很愚蠢。

對我來說,問題則是,什麼是創建這些管理的對象,周圍路過它們,然後要麼 1.儲蓄的約定改變 2.取消改變一個新的實體的 3.取消創建完全

Inafzigers上面的回答是這樣的,但爲什麼所有的屬性複製?我不能只是不保存我的更改?

蘋果CoreDataBooks似乎通過在prepareForSegue這方面(insertNewObjectForEntityForName)創建孩子 ManagedObjectContext和一個新的實體來解決這個問題,並在委託方法(當它回來): - 如果保存爲點擊後,它節省了這種新的ManagedObjectContext和存儲對象 父FetchedResultsContext - 如果取消被點擊它什麼也不做,實際上丟棄新的託管對象上下文,因此,據推測,新的對象

所以這威力是傳統的方法,除了:

  • 該示例的代碼中存在一個註釋(CoreDataBooks RootViewController.m),它聲明兩個託管上下文不是必需的,這意味着您可能只能使用一個。以下是完整的評論: 重要提示:沒有必要爲此使用第二個上下文。您可以使用現有的上下文,這可以簡化一些代碼 - 例如,您不需要執行兩次保存。不過,這種實現說明了一種有時可能有用的模式(您想要維護一組單獨編輯的模式)。

  • CoreDataBooks不使用UIManagedDocument - 不知道是否有差別

什麼我也不清楚是,我們真的用insertNewObjectForEntityForName創建管理對象?那麼只需創建對象,然後只在用戶點擊保存時才插入它呢?

另外如果我們做一個編輯和一個取消 - 我們可以使用撤消管理器來擺脫變化嗎?

+0

我建議在上下文中需要保留其他更改的情況下使用臨時對象,並且不能假定在啓動時已經保存了所有內容。如果你從一開始就知道沒有先前的編輯(或者如果存在的話你可以放心地丟棄它們),那麼你根本不需要臨時對象。我以爲我在答覆的第二句話中提到了這一點。 :) – lnafziger