1

私はCMIS(Content management interoperability services)屋外サーバーからデータをダウンロードするために使用しています。次のコードを使用していますが、ある程度は正常に動作しますが、アプリケーションがバックグラウンドになるとネットワーク接続が失われ、アプリがフォアグラウンドになるとダウンロードが再試行され、接続エラーが発生して失敗します。私は初心者なので、どんな助けでも大歓迎です。

- (void)testFileDownload
{
    [self runTest:^
     {
         [self.session retrieveObjectByPath:@"/ios-test" completionBlock:^(CMISObject *object, NSError *error) {
             CMISFolder *testFolder = (CMISFolder *)object;
             STAssertNil(error, @"Error while retrieving folder: %@", [error description]);
             STAssertNotNil(testFolder, @"folder object should not be nil");

             CMISOperationContext *operationContext = [CMISOperationContext defaultOperationContext];
             operationContext.maxItemsPerPage = 100;
             [testFolder retrieveChildrenWithOperationContext:operationContext completionBlock:^(CMISPagedResult *childrenResult, NSError *error) {
                 STAssertNil(error, @"Got error while retrieving children: %@", [error description]);
                 STAssertNotNil(childrenResult, @"childrenCollection should not be nil");

                 NSArray *children = childrenResult.resultArray;
                 STAssertNotNil(children, @"children should not be nil");
                 STAssertTrue([children count] >= 3, @"There should be at least 3 children");

                 CMISDocument *randomDoc = nil;
                 for (CMISObject *object in children)
                 {
                     if ([object class] == [CMISDocument class])
                     {
                         randomDoc = (CMISDocument *)object;
                     }
                 }

                 STAssertNotNil(randomDoc, @"Can only continue test if test folder contains at least one document");
                 NSLog(@"Fetching content stream for document %@", randomDoc.name);

                 // Writing content of CMIS document to local file
                 NSString *filePath = [NSString stringWithFormat:@"%@/testfile", NSTemporaryDirectory()];
                 //                NSString *filePath = @"testfile";
                 [randomDoc downloadContentToFile:filePath
                                  completionBlock:^(NSError *error) {
                                      if (error == nil) {
                                          // Assert File exists and check file length
                                          STAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:filePath], @"File does not exist");
                                          NSError *fileError = nil;
                                          NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&fileError];
                                          STAssertNil(fileError, @"Could not verify attributes of file %@: %@", filePath, [fileError description]);
                                          STAssertTrue([fileAttributes fileSize] > 10, @"Expected a file of at least 10 bytes, but found one of %d bytes", [fileAttributes fileSize]);

                                          // Nice boys clean up after themselves
                                          [[NSFileManager defaultManager] removeItemAtPath:filePath error:&fileError];
                                          STAssertNil(fileError, @"Could not remove file %@: %@", filePath, [fileError description]);
                                      } else {
                                          STAssertNil(error, @"Error while writing content: %@", [error description]);
                                      }
                                      self.testCompleted = YES;
                                  } progressBlock:nil];
             }];
         }];
     }];
}

ユーザーがホームキーを押しても、接続失敗は発生しません。マグネットカバーのふたが閉じているとき、またはタイムアウトがあるときのみ失敗します。

4

2 に答える 2

2

アプリがバックグラウンドに移動すると、OS は、アプリが中断される前に 5 秒間、実行中の操作を完了するようにアプリに与えます (RAM を保持しますが、アプリがメッセージを受信したり、何かを実行したりするのを停止します)。ユーザーがホーム ボタンを押したときに完了するまで実行する必要があるタスクがある場合は、バックグラウンド タスクを使用できます。アップルのドキュメントから:

アプリ デリゲートの applicationDidEnterBackground: メソッドには、タスクを終了して戻るのに約 5 秒かかります。実際には、このメソッドはできるだけ早く戻る必要があります。時間がなくなる前にメソッドが戻らない場合、アプリは強制終了され、メモリから消去されます。タスクの実行にさらに時間が必要な場合は、beginBackgroundTaskWithExpirationHandler: メソッドを呼び出してバックグラウンド実行時間を要求し、実行時間の長いタスクをセカンダリ スレッドで開始します。バックグラウンド タスクを開始するかどうかに関係なく、applicationDidEnterBackground: メソッドは 5 秒以内に終了する必要があります。

注: UIApplicationDidEnterBackgroundNotification 通知も送信され、アプリの関心のある部分にバックグラウンドに移行していることを知らせます。アプリ内のオブジェクトは、デフォルトの通知センターを使用して、この通知に登録できます。

http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.htmlから

于 2013-05-15T18:34:52.260 に答える
1

到達可能性コードを使用 ダウンロードしたデータを保存するには、次のコードを試してください。

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{
//try to access that local file for writing to it...
NSFileHandle *hFile = [NSFileHandle fileHandleForWritingAtPath:self.localPath];
//did we succeed in opening the existing file?
if (!hFile) 
{   //nope->create that file!
   [[NSFileManager defaultManager] createFileAtPath:self.localPath contents:nil attributes:nil];
   //try to open it again...
   hFile = [NSFileHandle fileHandleForWritingAtPath:self.localPath];
}
//did we finally get an accessable file?
if (!hFile)
{   //nope->bomb out!
   NSLog("could not write to file %@", self.localPath); 
   return;
}
//we never know - hence we better catch possible exceptions!
@try 
{
   //seek to the end of the file
   [hFile seekToEndOfFile];
   //finally write our data to it
   [hFile writeData:data];
}
@catch (NSException * e) 
{
   NSLog("exception when writing to file %@", self.localPath); 
   result = NO;
}
[hFile closeFile];
}
于 2013-05-15T19:05:59.407 に答える