.plist ファイルを使用して、iCloud を使用してデバイス間でデータを同期する Mac および iOS 用のアプリがあります。ときどき、特定のデバイスでクラッシュが繰り返されるというメールを誰かから受け取ります。(他のデバイスは問題ありません。) いずれの場合も、データを辞書に変換するために NSPropertyListSerialization を使用して、iCloud からファイルを読み込もうとしているときにアプリがクラッシュしました。いずれの場合も、ユーザーにアプリの iCloud データを削除してもらうことで問題は解決します。同じファイルが再び同期され、すべてが再び正常に機能します。
ここで使用する特定の例は Mac バージョンのものですが、iOS でもほぼ同じクラッシュが発生しました。クラッシュレポートから:
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: 0x000000000000000a, 0x0000000101ee2000
VM Regions Near 0x101ee2000:
VM_ALLOCATE 0000000101ee1000-0000000101ee2000 [ 4K] rw-/rwx SM=PRV
--> mapped file 0000000101ee2000-0000000101ee3000 [ 4K] r--/rwx SM=COW /Users/USER/Library/Mobile Documents/PB4R74AA4J~com~junecloud~Notefile/*/*.notefile
shared memory 0000000101ee3000-0000000101ee4000 [ 4K] rw-/rw- SM=SHM
その後:
Thread 7 Crashed:
0 libsystem_c.dylib 0x0000000105157013 bcmp + 19
1 com.apple.CoreFoundation 0x0000000101bbf4b0 __CFBinaryPlistGetTopLevelInfo + 80
2 com.apple.CoreFoundation 0x0000000101bbf36d __CFTryParseBinaryPlist + 93
3 com.apple.CoreFoundation 0x0000000101bbede2 _CFPropertyListCreateWithData + 146
4 com.apple.CoreFoundation 0x0000000101bcbdb0 CFPropertyListCreateWithData + 112
5 com.apple.Foundation 0x0000000101568b89 +[NSPropertyListSerialization propertyListWithData:options:format:error:] + 94
6 com.junecloud.Notefile-Helper 0x000000010107ad06 -[JUNNoteDocument readFromData:ofType:error:] + 64
7 com.apple.AppKit 0x000000010268d507 -[NSDocument readFromURL:ofType:error:] + 546
8 com.apple.AppKit 0x000000010228e3c8 -[NSDocument _initWithContentsOfURL:ofType:error:] + 135
9 com.apple.AppKit 0x000000010228e074 -[NSDocument initWithContentsOfURL:ofType:error:] + 262
10 com.junecloud.Notefile-Helper 0x000000010107cad8 -[JUNSyncDocument initWithFileURL:] + 213
11 com.junecloud.Notefile-Helper 0x0000000101079ec7 -[NotefileAppDelegate documentForURL:] + 68
12 com.junecloud.Notefile-Helper 0x00000001010825cb -[JUNSyncManager documentForURL:] + 76
13 com.junecloud.Notefile-Helper 0x000000010107d43c -[JUNSyncInOperation main] + 1340
14 com.apple.Foundation 0x0000000101563cd2 __NSThread__main__ + 1345
15 libsystem_c.dylib 0x00000001051697a2 _pthread_start + 327
16 libsystem_c.dylib 0x00000001051561e1 thread_start + 13
Thread 7 crashed with X86 Thread State (64-bit):
rax: 0x0000000000000062 rbx: 0x000000000000007b rcx: 0x000000010c2be868 rdx: 0x0000000000000007
rdi: 0x0000000101d1e151 rsi: 0x0000000101ee2000 rbp: 0x000000010c2be810 rsp: 0x000000010c2be7b8
r8: 0x000000010c2be870 r9: 0x0000000000000000 r10: 0x00007ff841c28900 r11: 0x00007ff841c186d8
r12: 0x000000010c2be870 r13: 0x0000000101ee2000 r14: 0x000000010c2beb00 r15: 0x000000010c2be980
rip: 0x0000000105157013 rfl: 0x0000000000010202 cr2: 0x0000000101ee2000
Logical CPU: 2
クラッシュしている関連するコードは次のとおりです。
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {
BOOL success = NO;
NSDictionary *dictionary = nil;
NSError *error = nil;
id plist = [NSPropertyListSerialization propertyListWithData:data
options:NSPropertyListImmutable format:NULL error:&error];
if (plist && [plist isKindOfClass:[NSDictionary class]]) {
dictionary = plist;
} else {
NSLog(@"Error opening document: %@ %@",error,[error userInfo]);
if (outError != NULL) *outError = error;
}
// Then it does some things with the dictionary if it's not nil
return success;
}
NSPropertyListSerialization が壊れたデータを詰まらせているだけだと思うのは正しいですか、それとも自分のコードで問題が発生する可能性が高いですか? 問題が NSPropertyListSerialization にある場合、アプリのクラッシュを防ぎ、問題をより適切に処理するためにできることはありますか?
問題が自分のコードにある可能性が高い場合、原因を追跡するにはどうすればよいですか? 自分で問題を再現できれば、これははるかに簡単になりますが、自分のデバイスでこのクラッシュを見たことはありません。明らかに、ユーザーが自分の iCloud アカウントへのアクセスを許可してくれるとは期待できません。
更新リクエストに応じて、ここに少しJUNSyncDocument
. iOS ではこれは UIDocument サブクラスであり、Mac では NSDocument サブクラスです。
- (id)initWithFileURL:(NSURL *)url {
#if TARGET_OS_IPHONE
self = [super initWithFileURL:url];
return self;
#else
NSError *error = nil;
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
if ((self = [super initWithContentsOfURL:url ofType:[self documentType] error:&error])) {
self.fileURL = url;
self.hasUndoManager = NO;
} else NSLog(@"Error initializing existing document: %@ %@",url,error);
} else {
if ((self = [super initWithType:[self documentType] error:&error])) {
self.fileURL = url;
self.hasUndoManager = NO;
} else NSLog(@"Error initializing new document: %@",error);
}
return self;
#endif
}
これはごちゃごちゃしているように見えます。ここでばかげたことをしていても驚かないでしょう。ただし、ほとんどの場合は問題なく動作します。それはから呼び出されNotefileAppDelegate
ます:
- (JUNSyncDocument *)documentForURL:(NSURL *)url {
JUNNoteDocument *document = [[JUNNoteDocument alloc] initWithFileURL:url];
return document;
}
これは次のように呼び出されJUNSyncManager
ます:
- (JUNSyncDocument *)documentForURL:(NSURL *)url {
return [self.delegate documentForURL:url];
}
によって呼び出されJUNSyncInOperation
ます:
JUNSyncDocument *document = [self.delegate documentForURL:self.url];
を使用してそのばかげたデリゲート チェーンを取り除くことができることに気付きましたがNSClassFromString
、それが問題に影響するかどうかはわかりません。