45

我有一個用戶界面來插入交易。一旦用戶點擊一個加號,他就得到了屏幕,我想實例化我的核心數據NSManagedObject實體,讓用戶在其上工作。然後當用戶點擊保存按鈕時,我將調用保存功能。有沒有一種方法來實例化NSManagedObject而不插入它?

這樣下來操作的代碼:

transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext]; 
//even if i dont call save: its going to show up on my table 
[self.managedObjectContext save:&error] 

P.S我在該表使用NSFetchedResultsController和我看到NSFetchedResultsController被插入部和對象表中。

我的想法是,如果有一種方法來實例化事務NSManagedObject我可以更新它與保存直到客戶端選擇。

回答

16

使用零MOC存在一個基本問題:不同MOC中的對象不應該彼此引用—這大概也適用於關係的一方具有零MOC時。如果你保存會發生什麼? (當你的應用程序的另一部分保存時會發生什麼?)

如果你的對象沒有關係,那麼你可以做很多事情(比如NSCoding)。

您可能能夠在NSPredicate中使用-[NSManagedObject isInserted](推測在插入和成功保存之間爲YES)。或者,您可以使用具有相同行爲的瞬態屬性(在awakeFromInsert中將其設置爲YES,在willSave中將其設置爲NO)。如果您的應用程序的不同部分保存,這兩種方式都可能會產生問題。

使用第二MOC是如何CoreData是「應該」被使用,雖然;它自動處理衝突檢測和解決方案。當然,每次改變時你都不想創建一個新的MOC;如果您不介意UI的某些部分在其他部分發現未保存的更改(MOC間通信的開銷可忽略不計),那麼通過緩慢的「用戶線程」讓未保存的更改有一個MOC可能是非常明智的。

+0

嗨@tc。我嘗試了第一個是insertIntoManagedObjectContext的響應:nil,但是當我想分配一個關係時,應用程序崩潰了:reason:'非法嘗試在不同上下文中的對象之間建立關係「類別」。所以我想我的問題是因爲它是不合法的上下文NSManaged對象和上下文管理對象之間的關係,什麼是解決方案? – 2010-10-06 14:09:38

+0

我最終創建了一個類別實體沒有上下文相同的方式,但是當它來保存我添加到上下文,然後它運作良好。 – 2010-10-06 14:31:04

+2

我可以證實此答案的正確性。我剛剛遇到了一個與上下文無關的問題。添加上下文之前分配給對象的屬性值在最終將對象添加到子上下文時不會傳播到父上下文。屬性在持久性存儲中以「nil」存儲。當我切換順序時(即在將屬性值插入上下文之後賦值),事情正常運行。這個故事的道德觀點是,沒有上下文的情況下實例化一個對象並不是一個好主意。 – 2014-03-21 07:06:38

8

您可以插入NSManagedObjectContext-[NSManagedObject initWithEntity:insertIntoManagedObjectContext:],傳遞nil作爲託管對象上下文。當然,你必須將它分配給上下文(在保存之前使用-[NSManageObjectContext insertObject:]),但據我所知,這並不是Core Data中的預期模式(但請參閱@ mzarra的回答here)。有一些棘手的排序問題(例如確保實例在預期有上下文之前被分配給上下文等)更爲標準的模式是創建一個新的託管對象上下文並將新對象插入該上下文當用戶保存時,保存並處理NSManagedObjectDidSaveNotification將這些更改合併到您的「主要」上下文中。如果用戶取消交易,您只需吹掉背景並繼續與您的業務相關即可。

+0

我想你的意思'NSManagedObject',不'NSManagedObjectContext'。無論哪種方式,它看起來並不像你可以改變一個NSManagedObject與—關聯,您可能使用'會混淆它的MOC - [的NSManagedObjectContext assignObject:toPersistentStore:]'。 – 2010-10-06 00:09:04

+0

@tc,感謝您的錯字捕捉。 – 2010-10-06 01:12:10

30

對於它的價值,Marcus Zarra似乎要推廣nil上下文方法,聲稱創建一個新的上下文是昂貴的。 ls,參見this answer也有類似的問題。

我目前使用的無背景的辦法也碰到了一些可能會感興趣的其他更新。要創建沒有上下文的管理對象,請使用NSManagedObjectinitWithEntity:insertIntoManagedObjectContext:方法。根據Apple對此方法的文檔:

If context is not nil , this method invokes [context insertObject:self] (which causes awakeFromInsert to be invoked).

這裏的含義很重要。在創建管理對象時使用nil上下文將阻止insertObject:被調用,並因此阻止awakeFromInsert被調用。因此,當使用nil上下文時,在awakeFromInsert中完成的任何對象初始化或默認屬性值設置都不會自動發生。底線:使用不帶上下文的管理對象時,awakeFromInsert不會自動調用,您可能需要額外的代碼才能進行補償。

+0

嗨這工作了一段時間,直到我試圖建立我的事務和NSManagedObject類別之間的關係。那麼應用程序就會因此而崩潰。有沒有辦法解決它? – 2010-10-06 14:14:26

+0

如果你需要建立關係,我會採用兩種背景方法。作爲tc。指出,不同上下文中的對象不應該相互引用。另一方面,您可以推遲設置這些關係,直到*將新的未關聯對象插入主要上下文之後。 – 2010-10-06 15:44:49

17

這裏是我的工作了:

上的負載,我們知道我們面對的是一個新的事務,我創建了一個斷章取義之一。

NSEntityDescription *entity = [NSEntityDescription entityForName:@"Transaction" inManagedObjectContext:self.managedObjectContext]; 
     transaction = (Transaction *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil]; 

那麼,當它來建立關係,船我這樣做:

if(transaction.managedObjectContext == nil){ 
     NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:self.managedObjectContext]; 
     Category *category = (Category *)[[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil]; 
     category.title = ((Category *)obj).title; 
     transaction.category = category; 
     [category release]; 
    } 
    else { 
     transaction.category = (Category *)obj; 
    } 

,並在年底節省:

if (transaction.managedObjectContext == nil) { 
     [self.managedObjectContext insertObject:transaction.category]; 
     [self.managedObjectContext insertObject:transaction]; 
    } 
    //NSLog(@"\n saving transaction\n%@", self.transaction); 

    NSError *error; 
    if (![self.managedObjectContext save:&error]) { 
     // Update to handle the error appropriately. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     exit(-1); // Fail 
    } 
+0

我想知道我是否可以做... transaction =(Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@「Transaction」inManagedObjectContext:context];然後transaction.managedObjectContext = nil;那會是錯的嗎? – yunas 2012-09-11 09:41:40

2

的NSManagedObject可以使用零作爲創建上下文,但如果有其他NSManagedObjects它必須鏈接到它將導致錯誤。我這樣做的方式是將上下文傳遞到目標屏幕,並在該屏幕中創建一個NSManagedObject。使所有更改鏈接其他NSManagedObjects。如果用戶點擊取消按鈕,我刪除NSManagedObject並保存上下文。如果用戶點擊保存按鈕,我更新NSManagedObject中的數據,將其保存到上下文中,然後釋放屏幕。在源屏幕中,我使用重新加載來更新表格。

刪除NSManagedObject在目的地屏幕給出了核心數據的時間來更新文件。這通常足以讓你在tableview中看不到變化。在iPhone日曆應用程序中,從節省的時間到顯示在桌面視圖中的時間都有延遲。從UI的角度來看,這可能被認爲是一件好事,您的用戶將專注於剛添加的行。我希望這有幫助。

-3
transaction = (Transaction *)[NSEntityDescription insertNewObjectForEntityForName:@"Transaction" inManagedObjectContext:nil]; 

如果最後一個參數是零,它會返回一個NSManagedObject沒有保存到數據庫

+0

這將導致失敗:***終止應用程序,由於未捕獲異常'NSInvalidArgumentException',原因:'+ entityForName:nil不是合法的NSManagedObjectContext參數搜索實體名稱... – c9s 2015-03-12 12:53:09

相關問題