保存時にIphone Core Dataがクラッシュする
-
22-07-2019 - |
質問
現在、Core Dataを使用してIphoneアプリケーションを作成していますが、[managedObjectContext save:&& error]コード行で EXC_BAD_ACCESS
エラーが発生します。このクラッシュは、特定のフィールドを変更した後にのみ発生します。より具体的には、エンティティには2つの文字列フィールド(約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
ご協力ありがとうございます。ありがとうございます。
UPDATE:また、プログラムがクラッシュしても、バックアップを開いたときにデータが正しく保存されました。 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
コードは以前は適切にフォーマットされていませんでした。このView Controllerが新しい「メッセージ」でない場合に作成されるとき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];
}
(最初のコードセットは、messsageViewが属するクラスであるMessageViewController.mファイルからのものです)
EditorViewControllerをモーダルビューとして表示してから戻る場合にのみクラッシュします。 textArrayとhtmlStringの行(モーダルビューが影響する唯一のもの)を次のように変更しても:
message.textArray = @"HELLO";
message.htmlString = @"HELLO";
まだクラッシュします。ただし、両方の行をコメントアウトしてもクラッシュしません。
したがって、モーダルビューを表示してからNSOManagedObjectのtextArrayまたはhtmlStringフィールドを編集しようとするとクラッシュするようです...
ビューを表示する場所:
- (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:@""]];
}
解決 2
問題を解決しましたが、実際の根本原因に取り組んでいるかどうかはわかりません。この行を追加すると、エラーは解消されました。
[managedObjectContext setRetainsRegisteredObjects:YES];
managedObjectContextを作成する場所。したがって、カウントの保持に関係していると思います。モーダルビューが表示されると、インスタンス変数が部分的または一時的に解放されるか、何かが発生するのではないかと思います。知りません。いずれにせよ、このエラーは解消され、プログラムは正常に動作するようになりました。
他のヒント
そのオブジェクトへの変更(挿入、更新、削除)が保留されている限り、コンテキストから管理対象オブジェクトへのアクセスを保持することのみが保証されます。 save:を呼び出すとすぐに、管理対象オブジェクトへの参照を失う可能性があります。
setRetainsRegisteredObjects:YESを設定するとエラーの表示が停止しますが、管理オブジェクトのライフタイムを管理オブジェクトコンテキストのライフタイムに依存するように設定するため、メモリ管理の問題が発生する可能性があります。アプリ全体でコンテキストを渡す場合、大きなオブジェクト階層があると、かなり大きくなる可能性があります。
こちらのAppleドキュメントで詳細を読むことができます: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdMemory.html 。
同じ問題を抱えている他の人を助け、上記のSteffの応答を強化するために、このエラーの原因としては、NSManagedObjectをリリースしようとしていることが考えられます。
iPhoneでCore Dataを使用すると、iPhoneシミュレーターのコンテンツと設定をリセットすることで解決される多くの面白い動作を見てきました。
私はこれが古いことを知っていますが、同じ問題を抱えていたので、問題を解決する方法についてタプペンスを追加すると考えましたそして、すべてが正常に動作しています:)ドキュメントによれば、コンテキストがそのすべてを管理するため、管理オブジェクトを手動で試してリリースすることはできません。とにかくそれは私の経験です。過剰にリリースされた値については、コードを検索してください。
FRCキャッシュをnilに設定する必要があります
オブジェクトが確実にフェッチされるようにすることで、同様の問題を解決しました。したがって、上記の例では:
if ( message == nil ) {
message = [NSEntityDescription insertNewObjectForEntityForName:@"MailMessage" inManagedObjectContext:self.managedObjectContext];
} else {
NSError *error = nil;
message = (MailMessage *)[managedObjectContext existingObjectWithID:[message objectID] error:&error];
}