0

3 つの別々のフィードからデータを収集する iPhone アプリを開発しています。applicationDidFinishLaunchingおよびで次applicationWillEnterForegroundの操作を行います。

[self emptySchedule];
[self populateSchedule];
[self emptyPlayers];
[self populatePlayers];
[self emptyNews];
[self populateNews];

空のメソッドは単にコア データから情報を削除し、populate メソッドはさまざまな Web json/xml フィードを呼び出してコア データに情報を追加します。これは非常に高速に行われるようです。しかし、これがアプリで情報を最新に保つための好ましい方法かどうか疑問に思っていました.

編集:

コンテキストを説明するために、空/移入に使用されるいくつかのメソッドを次に示します。

これはほとんどが非同期であるため、アプリケーションの起動時間に影響しますか?

- (void) emptySchedule
{
    NSFetchRequest * allEvents = [[NSFetchRequest alloc] init];
    [allEvents setEntity:[NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext]];
    [allEvents setIncludesPropertyValues:NO]; //only fetch the managedObjectID

    NSError * error = nil;
    NSArray * events = [self.managedObjectContext executeFetchRequest:allEvents error:&error];
    //error handling goes here
    for (NSManagedObject * event in events) {
        [self.managedObjectContext deleteObject:event];
    }
    NSError *saveError = nil;
    [self.managedObjectContext save:&saveError];
}

-(void)populateSchedule
{
    NSURL *url = [NSURL URLWithString:SCHEDULE_FEED_URL];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id schedule) 
                                         {
                                             for (NSDictionary *campEvent in schedule) 
                                             {
                                                 Event *event = nil;

                                                 event = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
                                                 event.eventName = [campEvent valueForKeyPath:@"eventName"];
                                                 event.ticketsRequired = [campEvent valueForKeyPath:@"ticketsRequired"];
                                                 event.location = [campEvent valueForKeyPath:@"location"];
                                                 event.practiceStart = [NSDate dateWithTimeIntervalSince1970:[[campEvent valueForKeyPath:@"practiceStart"] doubleValue]];
                                                 event.practiceEnd = [NSDate dateWithTimeIntervalSince1970:[[campEvent valueForKeyPath:@"practiceEnd"] doubleValue]];
                                             }
                                             NSError *saveError = nil;
                                             //Save inserts
                                             [self.managedObjectContext save:&saveError];

                                              //Notify other objects of this
                                             [[NSNotificationCenter defaultCenter] postNotificationName:@"populateSchedule" object:nil];

                                         } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
                                             UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error" message:@"Error Retrieving Data. Please try again later." delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
                                             [alert show];
                                         }];
    [operation start];
}
4

1 に答える 1

1

私の個人的な経験に基づいて答えようとします。たぶん、他の誰かがそれについて別の意見を持っているかもしれません。

あなたの場合、同期はアプリケーションのライフサイクルの段階でのみ実行されます。

だから、私は3分の1を追加します。ユーザーがそれを尋ねるとき。ただし、それはアプリケーションの性質に厳密に依存します。もう 1 つの方法は、定期的に起動してサーバーに新しいデータを送信するように要求するバックグラウンド スレッドを設定することです。これは、手動で同期するよりも複雑になる可能性があります。

これら 2 つの方法について、特定のバックグラウンド スレッドでインポート操作を実行します。独自の操作 (NSOperationこのタイプのタスクにはクラスもあります) を設定し、そこで処理を行うか、新しい iOS 5 Queue Core Data API を使用することができます。

emptyまだ(バックグラウンドのインポート)を行っていない場合は、実際のメソッドに対しても行ってください(この場合、 /のペアを統合するだけでよいと思いますpopulate)。このメカニズムにより、アプリケーションの起動を促進し、UI をフリーズさせることなく何が起こっているかをユーザーに伝えることができます: 「こんにちは、サーバーからデータを取得しています!お待ちください」 .

編集

あなたが追加したコードについては、私にとっては問題ありません。考慮事項は 2 つだけです。

まず、削除がメイン スレッドで実行される場合、削除するエントリが多数ある場合、メイン スレッドがブロックされる可能性があります。この場合、UI が応答しない可能性があります。とにかく、あなたは への良い仕事の設定setIncludesPropertyValuesをしましたNO

他のスニペットについては、データのダウンロードのみが非同期で実行されていると思います。完了ハンドラはメイン スレッドで実行され (たとえば で確認できますBOOL isMainThread = [NSThread isMainThread])、コア データ オブジェクトの作成とその相対的な保存が行われます。また、この場合、大量のデータがある場合、メイン スレッドがブロックされる可能性があります。

とにかく、いくつかのテストを行い、アプリの起動にそれほど時間がかからない場合は、コードをそのまま使用できます。何らかの遅延が発生し始めた場合は、バックグラウンドで Core Data 操作を実行できる可能性があります。

iOS 5 API がないと、save呼び出しの実行に時間がかかる可能性があります (データ全体ではなくチャンクを保存できるため) (特に、コア データ ファイルに格納するオブジェクトが多数ある場合)。iOS 5 以降では、新しいタイプのNSManagedObjectContext( queue concurrency type ) と親子コンテキストを利用できます。さらに、Core Data スタック全体を記述してUIManagedDocumentクラスを使用することを避けることができます。両方を使用するsaveことで、メイン スレッドをブロックすることなく、同時キューで実行できます。

それが役立つことを願っています。

于 2012-07-05T17:45:33.310 に答える