2012-03-17 60 views
0

我可以使用一些幫助來調試[context deleteObject:loan];命令上收到的EXC_BAD_ACCESS錯誤。在下面的代理方法中收到錯誤:核心數據上的訪問錯誤deleteObject

- (void)didCancelNewLoan:(Loan *)loan { 
    // save the context 
    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; 

    [context deleteObject:loan]; // *** EXC_BAD_ACCESS here *** 

// This method is called from a the following method in a second class: 

- (IBAction)cancel:(id)sender { 
    [delegate didCancelNewLoan:self.loan]; 
} 

// The loan ivar is created by the original class 
// in the below prepare for Segue method: 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 

    if ([segue.identifier isEqualToString:@"NewLoan"]) { 
     UINavigationController *navController = (UINavigationController *)[segue destinationViewController]; 
     LoanViewController *loanView = (LoanViewController *)[[navController viewControllers] lastObject]; 
     loanView.managedObjectContext = self.managedObjectContext; 
     loanView.delegate = self; 

     loanView.loan = [self createNewLoan]; 
     loanView.newLoan = YES; 
    } 


// Finally, the loan is created in the above 
// method's [self createNewLoan] command: 

- (NSManagedObject *)createNewLoan { 
    //create a new instance of the entity managed by the fetched results controller 
    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext]; 
    NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity]; 
    NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; 
    [newManagedObject setValue:[NSDate date] forKey:@"timeStamp"]; 

    CFUUIDRef uuid = CFUUIDCreate(NULL); 
    CFStringRef uuidstring = CFUUIDCreateString(NULL, uuid); 
    //NSString *identifierValue = (__bridge_transfer NSString *)uuidstring; 
    [newManagedObject setValue:(__bridge_transfer NSString *)uuidstring forKey:@"identifier"]; 
    CFRelease(uuid); 
    CFRelease(uuidstring); 

    NSError *error; 
    [self.fetchedResultsController performFetch:&error]; 
    NSLog(@"%i items in database", [[self.fetchedResultsController fetchedObjects] count]); 

    return newManagedObject; 
} 

感謝您查看上述方法。

回答

1

從你的代碼上面看,沒有什麼是凸現出被錯誤地進行。

我想知道你是否正在處理兩個不同的託管對象上下文而沒有意識到它?您將不得不在創建對象的地方設置一些斷點,並查看是否可能是這種情況。

此外,爲什麼您必須通過fetchedResultsController獲取對上下文的引用(如果您已在self.managedObjectContext中爲其指定屬性)?

另一件事是爲什麼當您創建一個新的Loan對象時,您需要再次撥打fetchedResultsControllerperformFetch:?您的數據是否以表格視圖呈現,並且您是否實施了NSFetchedResultsController委託方法?

該調用看起來沒有必要,並且可能會導致由提取創建的緩存問題。請參閱此鏈接下的「修改獲取請求」部分http://developer.apple.com/library/ios/documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40008227-CH1-SW24

最後,直接在接收到該操作的視圖控制器中嘗試刪除操作,而不是將其傳遞給委託(僅僅爲了消除某些已被dealloc'你不知道)。

這裏就是我想要做的:

- (IBAction)cancel:(id)sender 
{ 
    NSError *error; 
    NSManagedObjectContext *context = [self.loan managedObjectContext]; 
    [context deleteObject:self.loan]; 
    if (![context save:&error]) 
     NSLog (@"Error saving context: %@", error); 
} 
+0

感謝您的反饋。我嘗試了一些建議。當在收到該操作的視圖控制器中運行上面的代碼時,我得到相同的錯誤。我打開殭屍,並獲得更多的錯誤信息:「[CFString保留]:消息發送到解除分配的實例...」,是的,你是正確的數據顯示在tableview中,我已經在接收中實現NSFetchedResultsController委託方法視圖控制器。 – Jack 2012-03-19 14:51:47

+0

你可以嘗試'__bridge'你的CFString而不是'__bridge__transfer'嗎?看起來您的CFString對象正在儘快發佈。 – Rog 2012-03-19 19:30:53

+0

或者保留原樣,根據我對文檔的理解,不要發佈'uuidstring',因爲ARC正在爲你做這件事。 – Rog 2012-03-19 19:36:09

2

猜測#1:您正在訪問一個釋放對象。調試:打開殭屍,看看會發生什麼。

更新:這裏是你如何在Xcode 5開啓殭屍:

產品>方案>編輯方案,選擇診斷選項卡,勾選 「啓用殭屍對象」

scheme diagnostics settings

爲舊的Xcode

,編輯您的構建設置,在您的構建方案中添加並啓用這些參數:

(and and check these arguments in your build scheme)


猜測#2:你有一個多線程應用程序和要訪問來自不同線程的被管理對象的上下文,這是一個無無。

你可以在你的刪除添加斷言:

assert([ NSThread isMainThread ]) ; 
0

我有一個壞的訪問,因爲解分配的UIViewController是一個NSFetchedResultsController它有一個代表。

NSFetchedResultsController被解除分配 - 但是當設置一個委託時,它會觀察NSManagedObjectContext的變化,所以當NSManagedObjectContext被保存時 - 當試圖通知NSFetchedResultsController關於變化時會發生錯誤的訪問。

解決方法是取消分配後清除NSFetchedResultsController的委託。

- (void)dealloc { 
    fetchedResultsController.delegate = nil; 
}