2011-08-04 14 views
3

質問は簡単です:起動するたびにアップデートがあれば、私のappコントロール。更新がある場合、ポップアップが表示され、[はい]または[いいえ]が選択されます。ユーザーが「はい」をタップすると4つのメソッドが起動しますこれらのメソッドは、XMLファイルをダウンロードし、CoreDataをアップロードします。これは、アラートのコードです:iOS - バックグラウンドプロセスとUIアップデート

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 

    if (buttonIndex==1) { 
     [self showActivityViewer]; 
     [self downloadControlAndUpdatePoi]; 
     [self downloadControlAndUpdateItinerari]; 
     [self downloadControlAndUpdateArtisti]; 
     [self downloadControlAndUpdateEventi]; 
     [self hideActivityViewer]; 
     NSLog(@"AGGIORNA"); 
    } else { 
     NSLog(@"NON AGGIORNARE"); 
     return; 
    } 
} 

しかし、問題があります:ユーザータップはいアラートが消え、すべてのメソッドが終了するまで画面に残りません。私はスタートをタップしますが、アクティビティビューアは表示されません。

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 

    if (buttonIndex==1) { 
     [self showActivityViewer]; 
     [NSThread detachNewThreadSelector:@selector(startDownloads) toTarget:self withObject:nil]; 
     [self hideActivityViewer]; 
     NSLog(@"AGGIORNA"); 
    } else { 
     NSLog(@"NON AGGIORNARE"); 
     return; 
    } 
} 

-(void)startDownloads { 
    NSInvocationOperation *opPoi=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdatePoi) object:nil]; 
    NSInvocationOperation *opItinerari=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdateItinerari) object:nil]; 
    NSInvocationOperation *opArtisti=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdateArtisti) object:nil]; 
    NSInvocationOperation *opEventi=[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadControlAndUpdateEventi) object:nil]; 
    NSArray *operations=[[NSArray alloc] initWithObjects:opPoi,opItinerari,opArtisti,opEventi, nil]; 
    NSOperationQueue *queue=[[NSOperationQueue alloc] init]; 
    [queue addOperations:operations waitUntilFinished:YES]; 
    [queue waitUntilAllOperationsAreFinished]; 

} 

も、ここでの問題があります。だから私は、この他のコードを試してみてください。アラートが消え、スレッドが次々に4つの方法を開始して実行します。

2番目のコードと同じようにバックグラウンドで実行するプロセスが必要ですが、showActityViewerメソッドを実行してスピナーを表示する必要があります。

ありがとうございました:)

答えて

5

最初のものが最初です。セカンダリスレッドですでに実行されているため、4つの操作を並行して実行する必要はないため、4つの操作を開始する必要はありません。あなたは、単に行うことができます。なかでも

-(void)startDownloads { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    [self downloadControlAndUpdatePoi]; 
    [self downloadControlAndUpdateItinerari]; 
    [self downloadControlAndUpdateArtisti]; 
    [self downloadControlAndUpdateEventi]; 
    [pool release]; 
} 

、あなたはdownloadControl*方法でautoreleaseを使用する場合startDownloadsに自動解放プールを定義する必要がある、そうでなければ私はあなたがリークを持っているだろうと思います。

[self hideActivityViewer]; 

すぐデタッチ後:アクティビティインジケータが表示されない理由として

、それはあなたが呼び出しているという事実に依存します。だから、あなたはそれを見せて、それを取り除いています。イベントの前に、UIはそれ自身を更新する時間があります。そこからその行を削除し、このようstartDownloadsを書き換える:ここ

-(void)startDownloads { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    [self downloadControlAndUpdatePoi]; 
    [self downloadControlAndUpdateItinerari]; 
    [self downloadControlAndUpdateArtisti]; 
    [self downloadControlAndUpdateEventi]; 
    [self performSelectorOnMainThread:@selector(hideActivityViewer) withObject:nil waitUntilDone:NO]; 

    [pool release]; 
} 

のみメインスレッドが安全UIKitを使用することができますので、私はhideActivityViewerにメインスレッドに呼び出していますことに注意してください。 EDIT:

私はあなたがダウンロード方式でコアデータを使用していたことを知らなかった...

Concurrency with Core Dataを見てください。少なくとも、セカンダリスレッドのために別個のマネージオブジェクトコンテキストを使用することで、コードをちょっと調整する必要があります(モックを作成することが可能かどうかは分かりません)。

this tutorial from Cocoa is my Girlfriendもご覧ください。

すべてのことに代わる方法として、あなたがやって考えることができます:

if (buttonIndex==1) { 
    [self showActivityViewer]; 
    [self performSelector:@selector(startDownloads) withObject:nil afterDelay:0]; 
    NSLog(@"AGGIORNA"); 
} else { 
    NSLog(@"NON AGGIORNARE"); 
    return; 
} 

で:

-(void)startDownloads { 
    [self downloadControlAndUpdatePoi]; 
    [self downloadControlAndUpdateItinerari]; 
    [self downloadControlAndUpdateArtisti]; 
    [self downloadControlAndUpdateEventi]; 
    [self hideActivityViewer]; 
} 

これは全くのスレッドを使用していませんが、私は活動の視聴者がすることを確認していないが何の不具合もなく表示する。必要に応じてもう1つのレベルのハッキングがあり、遅れを指定することができます

[self performSelector:@selector(startDownloads) withObject:nil afterDelay:0.1]; 
+0

私はどのようにstartDownloadsを呼び出す必要がありますか?ユーザーが「はい」をタップした後、NSThreadのデタッチまたは[self startDownloads]を使用しますか? –

+0

申し訳ありませんが、detachThread;あなたはこれを正しくやっています。唯一のポイントは、startDownloadsでより多くの非同期操作を必要としないことです。 – sergio

+0

これは問題ありませんが、大きな問題が発生しました。私のdownloadAndControl *メソッドはCoreDataで動作します。このソリューションでは、CoreDataのメソッドsaveでNSInternalInconsistencyExceptionが発生します。 –

関連する問題