Сбой данных Iphone Core при сохранении

В настоящее время я пишу приложение для Iphone с использованием Core Data и получаю сообщение об ошибке EXC_BAD_ACCESS во время строки кода [managedObjectContext save: && error]. Этот сбой происходит только после изменения определенных полей. В частности, у моей сущности есть два строковых поля (из примерно 10 полей), которые получают свои значения из возврата модального контроллера представления (например, текстового редактора). Сбой также происходит только после редактирования этих полей, когда я впервые ввожу в них значение, все работает нормально.

Причина, по которой у меня есть строка с конструкторами формата только со строками, заключается в том, что я пытался скопировать конструкцию ... не уверен, что это произойдет автоматически? Думал, что, возможно, сохранить / освободить сообщения из этих строк (эти два из контроллера модального представления), были выпущены при увольнении контроллера модального представления или что-то в этом роде. Думаю, нет, потому что это все еще не работает.

Вот фрагмент кода, который дает сбой:

[ИЗМЕНИТЬ]

        - (void)actionSheet:(UIActionSheet *)modalView clickedButtonAtIndex:    (NSInteger)buttonIndex
      switch(buttonIndex) {
              case 0: {
                if(message == nil) {
                  message = [NSEntityDescription insertNewObjectForEntityForName:@"MailMessage" inManagedObjectContext:self.managedObjectContext];
                }
                message.toString = txtTo.text;
                message.fromString = txtFrom.text;
                message.subjectString = txtSubject.text;
                message.backgroundColor = [NSNumber numberWithInt:[bgColor intValue]];
                message.textArray = [NSString stringWithFormat:@"%@", stringTextArray];
                message.htmlString = [NSString stringWithFormat:@"%@", stringHTML];
                message.timeStamp = [NSDate date];
                message.statusCode = [NSNumber numberWithInt:0];
                NSError *error = nil;
                if (![message.managedObjectContext save:&error]) {
                    abort();
                }   
                break;
               }
              case 1: {
             break;
              }
      }
      if(buttonIndex != modalView.cancelButtonIndex) {
      [webViewBody loadHTMLString:@"<html><head></head><body></body></html>" baseURL:[NSURL URLWithString:@""]];
      [self.navigationController popToRootViewControllerAnimated:YES];
}

}

А вот и аварийный журнал:

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000015
Crashed Thread:  0

Thread 0 Crashed:
0   libobjc.A.dylib                 0x30011940 objc_msgSend + 20
1   CoreData                        0x367f7d3e -[NSKnownKeysDictionary1 dealloc] + 82
2   CoreData                        0x367f7cda -[NSKnownKeysDictionary1 release] + 34
3   CoreData                        0x3687eec4 -[NSManagedObject(_NSInternalMethods) _setOriginalSnapshot__:] + 40
4   CoreData                        0x36821030 -[NSManagedObjectContext(_NSInternalAdditions) _clearOriginalSnapshotAndInitializeRec:] + 16
5   CoreData                        0x368205f2 -[NSManagedObjectContext(_NSInternalAdditions) _didSaveChanges] + 958
6   CoreData                        0x368133bc -[NSManagedObjectContext save:] + 412
7   Decome                          0x0001fdd6 -[CreateMessageViewController actionSheet:clickedButtonAtIndex:] (CreateMessageViewController.m:163)
8   UIKit                           0x30a6cbd8 -[UIActionSheet(Private) _buttonClicked:] + 256
9   CoreFoundation                  0x30256dd4 -[NSObject performSelector:withObject:withObject:] + 20
10  UIKit                           0x3096e0d0 -[UIApplication sendAction:to:from:forEvent:] + 128
11  UIKit                           0x3096e038 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 32
12  UIKit                           0x3096e000 -[UIControl sendAction:to:forEvent:] + 44
13  UIKit                           0x3096dc58 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 528
14  UIKit                           0x309a6e9c -[UIControl touchesEnded:withEvent:] + 452
15  UIKit                           0x309a60d4 -[UIWindow _sendTouchesForEvent:] + 520
16  UIKit                           0x309a5464 -[UIWindow sendEvent:] + 108
17  UIKit                           0x30936e3c -[UIApplication sendEvent:] + 400

Любая помощь приветствуется, спасибо.

ОБНОВЛЕНИЕ: Кроме того, даже если программа вылетает, когда я открываю ее резервную копию, данные сохраняются правильно. Таким образом, EXC_BAD_ACCESS должен произойти после того, как сохранение зашло, по крайней мере, достаточно далеко, чтобы сохранить его в постоянном хранилище, я думаю.

Если я закомментирую строку сохранения, код теперь работает нормально. Но он не сохраняется после закрытия и выхода. Если я запустил строку сохранения в моей функции willAppear контроллеров корневого представления, она выдаст ту же ошибку EXC_BAD_ACCESS. Консоль не говорит ничего, кроме EXC_BAD_ACCESS, если я выполняю обратную трассировку, я получаю:

#0  0x30011940 in objc_msgSend ()
#1  0x367f7d44 in -[NSKnownKeysDictionary1 dealloc] ()
#2  0x367f7ce0 in -[NSKnownKeysDictionary1 release] ()
#3  0x3687eeca in -[NSManagedObject(_NSInternalMethods) _setOriginalSnapshot__:] ()
#4  0x36821036 in -[NSManagedObjectContext(_NSInternalAdditions) _clearOriginalSnapshotAndInitializeRec:] ()
#5  0x368205f8 in -[NSManagedObjectContext(_NSInternalAdditions) _didSaveChanges] ()
#6  0x368133c2 in -[NSManagedObjectContext save:] ()
#7  0x0000314e in -[RootViewController viewWillAppear:] (self=0x11b560, _cmd=0x3014ecac, animated=1 '\001') at /Users/inckbmj/Desktop/iphone/Decome/Classes/RootViewController.m:85

Извините, код раньше был неправильно отформатирован. Когда этот контроллер представления создается, если это не новое «сообщение», ему передается объект сообщения, полученный из fetchedResultsController следующим образом:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    MailMessage *aMessage = (MailMessage *)[fetchedResultsController objectAtIndexPath:indexPath];
    [messageView loadMessage:aMessage viewOnly:NO usingTemplate:NO];
    messageView.managedObjectContext = self.managedObjectContext;
    [self.navigationController pushViewController:messageView animated:YES]; 
}

(первый набор кода взят из файла MessageViewController.m, который является классом, которым является messsageView)

Он вылетает только в том случае, если я представляю свой EditorViewController как модальное представление, а затем возвращаюсь. Даже если я изменю строки textArray и htmlString (это единственное, на что влияет модальное представление) на:

message.textArray = @"HELLO";
message.htmlString = @"HELLO";

он все еще вылетает. Если я закомментирую обе строки, но это не сработает.

Кажется, что он вылетает, если я представляю модальное представление, а затем пытаюсь отредактировать поля textArray или htmlString моего NSOManagedObject ...

Вот где я представляю вид:

- (void) touchesEnded: (NSSet *) touches withEvent: (UIEvent *) event {
    if(!viewOnly) {
        UITouch *touch = [touches anyObject];
        CGPoint location = [touch locationInView: txtTo];
    location = [touch locationInView: webViewBody];
        if(CGRectContainsPoint(webViewBody.bounds, location)) {
            [editor loadTextArrayString:stringTextArray];
            [self presentModalViewController:editor animated:YES];
        }
    }
}

и где я его отклоняю:

-(void)returnWithTextArray:(NSString *)arrayString HTML:(NSString *)html bgColor:(NSNumber *)numColor {
    [self dismissModalViewControllerAnimated:YES];
    self.stringTextArray = [NSString stringWithFormat:@"%@", arrayString];
    self.stringHTML = [NSString stringWithFormat:@"%@", html];
    self.bgColor = [NSNumber numberWithInt:[numColor intValue]];
    [webViewBody loadHTMLString:self.stringHTML baseURL:[NSURL URLWithString:@""]];
}

person kiyoshi    schedule 05.08.2009    source источник
comment
Может быть, вы можете сначала прокомментировать некоторые изменения в ваших атрибутах и ​​попробовать их один за другим, чтобы увидеть, какое из них вызывает сбой после изменения и сохранения.   -  person digdog    schedule 05.08.2009
comment
Кажется, это не вызвано каким-либо из полей, я думаю, что это должно быть связано с представлением модального представления ... Но я понятия не имею, почему. Все, что я делаю, это представляю точку зрения, а затем отклоняю ее ...   -  person kiyoshi    schedule 05.08.2009
comment
Я думаю, вы могли смотреть не в том месте. 1. Закомментируйте ВСЕ приведенный выше код сохранения основных данных. или просто добавьте обратный вызов в самом верху, чтобы этот код никогда не запускался. ТЕСТ на сбой. 2. Если сбоя не произошло, ОК, это должно быть в основных данных. Сделайте все, но не вызывайте функцию сохранения, последние несколько строк. 3. Покажите нам весь код для этой функции, так как мне интересно, как вы заполняете сообщение, если оно не равно нулю. 4. Что говорит консоль. Он должен дать вам более подробную информацию о том, что произошло.   -  person John Ballinger    schedule 06.08.2009
comment
Отредактировал мое сообщение, чтобы добавить больше кода. Он не вылетает, если я закомментирую сохранение. Я запускаю тот же код, если сообщение не равно нулю, это просто изменяет объект MailMessage, который я передал ему при нажатии контроллера представления. Все, что говорит консоль, - это EXC_BAD_ACCESS.   -  person kiyoshi    schedule 06.08.2009


Ответы (7)


Вы гарантированно сохраните доступ к управляемому объекту из контекста только до тех пор, пока для этого объекта ожидается изменение (вставка, обновление, удаление). Как только вы вызовете save :, вы можете потерять ссылку на управляемый объект.

Хотя вы перестали получать сообщение об ошибке при установке setRetainsRegisteredObjects: YES, возможно, вы столкнулись с проблемой управления памятью, поскольку вы устанавливаете время жизни управляемого объекта в зависимости от времени жизни контекста управляемого объекта. Если вы передаете свой контекст по всему приложению, он может стать довольно большим, если у вас есть большая иерархия объектов.

Вы можете прочитать больше в документации Apple здесь: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreData/MO_Lifecycle.html

person Tony Lenzi    schedule 02.12.2010

Проблема решена, хотя я не уверен, что устраняю настоящую основную причину. Ошибка была устранена, когда я добавил эту строку:

[managedObjectContext setRetainsRegisteredObjects:YES];

Туда, где я создаю managedObjectContext. Так что, я думаю, это было связано с удержанием счетов. Я предполагаю, что, возможно, переменные экземпляра будут частично или временно освобождены или что-то в этом роде, когда представлены модальные представления? Я не знаю. В любом случае эту ошибку устранили, программа теперь работает нормально.

person kiyoshi    schedule 10.08.2009
comment
У меня аналогичная проблема - тоже исправлена ​​с помощью указанной вами директивы. Чего я не знаю, так это ... ожидается ли, что теперь мы вручную выпустим каждую сущность, управляемую этим moc? - person Luther Baker; 01.09.2009
comment
Хотя это может исправить вашу проблему, ваши рассуждения несколько ошибочны. Мой ответ ниже объясняет, почему save: вызывает вашу проблему и указывает на документы Apple. - person Tony Lenzi; 02.12.2010
comment
Привет. Несохраненные управляемые объекты освобождаются при вызове функции save. Новые управляемые объекты должны быть загружены из вашего контроллера результатов выборки. - person stephen; 28.08.2012

Просто чтобы помочь другим, у которых есть такая же проблема, и подкрепить ответ Стефф выше, вероятная причина этой ошибки заключается в том, что вы пытаетесь выпустить NSManagedObject.

person Rog    schedule 11.10.2010

Я видел много забавного поведения с CoreData на iPhone, которое было решено путем сброса содержимого и настроек в симуляторе iPhone.

person Michael Sharek    schedule 05.08.2009
comment
Хотя запускал его на ipod touch, но да, попытался сбросить содержимое безрезультатно :(. - person kiyoshi; 06.08.2009

Я знаю, что это старый, но у меня была такая же проблема, поэтому я подумал, что добавлю свое мнение о том, как я решил проблему, моя была вызвана ручным выпуском управляемого объекта в модальном представлении, я удалил вызовы освобождения, и все работает нормально :) в соответствии с документами вам все равно не следует вручную пытаться освободить управляемые объекты, так как контекст будет следить за всем этим. Во всяком случае, это мой опыт, ищите в своем коде чрезмерно выпущенные значения.

person Steff    schedule 10.08.2010

Вы должны установить кеш FRC в ноль

person Greg    schedule 02.09.2010

Я решил аналогичную проблему, убедившись, что объект извлечен, поэтому в приведенном выше примере:

if ( message == nil ) {
    message = [NSEntityDescription insertNewObjectForEntityForName:@"MailMessage" inManagedObjectContext:self.managedObjectContext];
} else {
    NSError *error = nil;
    message = (MailMessage *)[managedObjectContext existingObjectWithID:[message objectID] error:&error];
}
person Khurram Ali    schedule 19.12.2012