1 つのデバイスでアプリから iCloud コンテナーに単純なファイルを書き込むことができず、2 番目のデバイスでアプリを初めて実行したときに同じファイルを正常に読み取ることができません。
このテスト シナリオは、新しくリセットされたデバイスのペアで空の Ubiquity コンテナーを使用して開始しました。以下は、私が抱えている問題を示すテスト ケース コードとコンソール ログです。以下のコードはすべてバックグラウンド スレッドで実行されます。
最初のデバイスにテスト ケースをインストールして実行します。このコードは、ユビキタス コンテナーで特定のファイルを探し、見つからない場合は作成します。明らかに、これは最初のデバイスで初めて実行するときに予想されます。私は、アプリが新たにインストールされて 2 番目のデバイスで実行されたときに、最初のデバイスで作成されたファイルの内容を見つけて読み取ることができることを期待 (期待) していました。リセットされたデバイスに新しくインストールされたアプリは、既存のファイルを見つけて読み取ることができず、新しいファイルを作成する必要があると常に考えているようです。残念ながら、ユビキタス コンテナー内のファイルが既に存在する場合は置き換えられます。
ただし、最初の試行 (2 番目のデバイスで) がファイルの検索と読み取りに失敗した後、アプリを削除し、再インストールしてから同じデバイスで再実行すると、ファイルが検出され、読み取ることができます。その現在の内容。アプリを最初に実行すると、ファイルがユビキタス キャッシュに読み込まれるように見えますが、アプリで見つけられる状態ではありません。アプリの 2 回目の実行では、キャッシュ内のファイルが見つかったようです。
iOSデバイスでファイルのダウンロードを開始することになっていることは知っていますが、デバイスで初めて、「ファイルが見つかりません」と報告されます。ここで他に何かする必要がありますか?それとも、これは新しいバグまたは既知のバグのように見えますか?
次のコードは、ユビキタス コンテナー内のトークン ファイルの存在を判断し、読み取り可能であることを確認するために使用されます。
NSError *error;
BOOL rc;
NSFileManager *fm = [[NSFileManager alloc] init];
NSURL *ubiquityURL = [fm URLForUbiquityContainerIdentifier:nil];
NSURL *tokenURL = [ubiquityURL URLByAppendingPathComponent:@"iCloudTokenFile"];
NSLog(@"isTokenFilePresentAtUrl: Entered for Device Name: %@", [[UIDevice currentDevice] name]);
error = nil;
rc = [fm startDownloadingUbiquitousItemAtURL:tokenURL error:&error];
NSLog(@"startDownloadingUbiquitousItemAtURL: %d Error: %@(%d)", rc, error.domain, error.code);
rc = [fm isUbiquitousItemAtURL:tokenURL];
NSLog(@"isUbiquitousItemAtURL: %d", rc);
NSNumber *isUbiquitousItem = nil;
error = nil;
rc = [tokenURL getResourceValue:&isUbiquitousItem forKey:NSURLIsUbiquitousItemKey error:&error];
NSLog(@"getResourceValue: %d isUbiquitousItem: %@ Error: %@(%d)", rc, isUbiquitousItem, error.domain, error.code);
NSNumber *isDownloading = nil;
error = nil;
rc = [tokenURL getResourceValue:&isDownloading forKey:NSURLUbiquitousItemIsDownloadingKey error:&error];
NSLog(@"getResourceValue: %d isDownloading: %@ Error: %@(%d)", rc, isDownloading, error.domain, error.code);
NSNumber *isDownloaded = nil;
error = nil;
rc = [tokenURL getResourceValue:&isDownloaded forKey:NSURLUbiquitousItemIsDownloadedKey error:&error];
NSLog(@"getResourceValue: %d isDownloaded: %@ Error: %@(%d)", rc, isDownloaded, error.domain, error.code);
次のコードは、ユビキタス コンテナーからトークン ファイルを読み取ろうとするために使用されます。
__block BOOL success = NO;
__block NSError *error = nil;
NSFileCoordinator *fc = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
[fc coordinateReadingItemAtURL:tokenURL
options:NSFileCoordinatorReadingWithoutChanges
error:&error
byAccessor:^(NSURL *newURL)
{
NSLog(@"readTokenFileFromUrl: Trying to read Token File.");
NSNumber *isDownloaded = nil;
error = nil;
BOOL rc = [tokenURL getResourceValue:&isDownloaded forKey:NSURLUbiquitousItemIsDownloadedKey error:&error];
NSLog(@"getResourceValue: %d isDownloaded: %@ Error: %@(%d)", rc, isDownloaded, error.domain, error.code);
NSString *uuidString = nil;
NSError *blockerror = nil;
uuidString = [NSString stringWithContentsOfURL:newURL
encoding:NSUTF8StringEncoding
error:&blockerror];
NSLog(@"readTokenFileFromUrl: Token read from file: %@", uuidString);
}];
次のコードは、既存のトークン ファイルを読み取ることができない場合にトークン ファイルをユビキタス コンテナーに書き込むために使用されます。このコードは、最初のデバイスで 1 回だけ実行されると予想していました。
NSFileCoordinator *fc = [[NSFileCoordinator alloc] initWithFilePresenter:nil];
NSError *error = nil;
[fc coordinateWritingItemAtURL:tokenURL
options:NSFileCoordinatorWritingForReplacing
error:&error
byAccessor:^(NSURL *newURL)
{
NSUUID *uuid = [[NSUUID alloc] init];
NSString *uuidString = [uuid UUIDString];
NSError *blockerror = nil;
NSLog(@"writeTokenFileToUrl: Writing token to file: %@", uuidString);
[uuidString writeToURL:newURL
atomically:YES
encoding:NSUTF8StringEncoding
error:&blockerror];
}];
アプリは「Red iPod touch」に初めてインストールして実行します。
isTokenFilePresentAtUrl: Entered for Device Name: Red iPod touch
startDownloadingUbiquitousItemAtURL: 0 Error: NSCocoaErrorDomain(4)
isUbiquitousItemAtURL: 0
getResourceValue: 0 isUbiquitousItem: (null) Error: NSPOSIXErrorDomain(2)
getResourceValue: 0 isDownloading: (null) Error: NSPOSIXErrorDomain(2)
getResourceValue: 0 isDownloaded: (null) Error: NSPOSIXErrorDomain(2)
readTokenFileFromUrl: Trying to read Token File.
getResourceValue: 0 isDownloaded: (null) Error: NSPOSIXErrorDomain(2)
readTokenFileFromUrl: Token from File: (null)
readTokenFileFromUrl: Error reading uuid Token from File: NSCocoaErrorDomain(260)
loadiCloudStore: isUbiquitousItemAtURL: Token File actually does not appear to be present.
writeTokenFileToUrl: Writing token to file: 6AAA8D81-4BB5-4BF4-AD31-E152D3BADD13
この時点で、developer.icloud.com Web サイトを介して、ファイルが Ubiquity Container に存在することが確認されます。アプリは、「Blue iPod touch」という名前の 2 番目のデバイスに初めてインストールされ、実行されます。
isTokenFilePresentAtUrl: Entered for Device Name: Blue iPod touch
startDownloadingUbiquitousItemAtURL: 0 Error: NSCocoaErrorDomain(4)
isUbiquitousItemAtURL: 0
getResourceValue: 0 isUbiquitousItem: (null) Error: NSPOSIXErrorDomain(2)
getResourceValue: 0 isDownloading: (null) Error: NSPOSIXErrorDomain(2)
getResourceValue: 0 isDownloaded: (null) Error: NSPOSIXErrorDomain(2)
readTokenFileFromUrl: Trying to read Token File.
getResourceValue: 0 isDownloaded: (null) Error: NSPOSIXErrorDomain(2)
readTokenFileFromUrl: Token from File: (null)
readTokenFileFromUrl: Error reading uuid Token from File: NSCocoaErrorDomain(260)
このテストでは、アプリは読み取りを試行した後に停止され、トークン ファイルの書き込みまたは置換を試行することはできません。その後、アプリは強制終了され、削除され、再インストールされ、Blue iPod touch で再び実行されます。
isTokenFilePresentAtUrl: Entered for Device Name: Blue iPod touch
startDownloadingUbiquitousItemAtURL: 1 Error: (null)(0)
isUbiquitousItemAtURL: 1
getResourceValue: 1 isUbiquitousItem: 1 Error: (null)(0)
getResourceValue: 1 isDownloading: 1 Error: (null)(0)
getResourceValue: 1 isDownloaded: 0 Error: (null)(0)
readTokenFileFromUrl: Trying to read Token File.
getResourceValue: 1 isDownloaded: 0 Error: (null)(0)
readTokenFileFromUrl: Token read from file: 6AAA8D81-4BB5-4BF4-AD31-E152D3BADD13
今回は、期待される内容のファイルを見つけて読み取ります。