1

私は MagicalRecord を使用しています。ビュー コントローラーの 1 つで、データ ソースはデータベースからのデータをフィードします。給餌プロセスには複数のステップが含まれているため、GCD を使用してプロセス全体をスピードアップしようとしました。一般的なプロセスはそのように見えます。

globalSummary でアクセス プロパティを取得した後に行う作業。問題は、アプリが dispatch_group_wait でハングすることです。ステップに作業を追加しようとしましたが、最初は機能しますが、さらに作業を追加すると、コードを段階的に実行すると機能しますが、実行すると機能しません。

アプローチに何か問題がありますか、それとも何らかの形で MagicalRecord と競合しますか?

- (NSArray *)dataSource
{
    if (_dataSource == nil) {

    _dataSource = [NSMutableArray array];
    NSManagedObjectContext *privateContext = [NSManagedObjectContext contextWithStoreCoordinator:[NSPersistentStoreCoordinator defaultStoreCoordinator]];

    GlobalSummary *globalSummary = [GlobalSummary insertInManagedObjectContext:privateContext]; // holds a bunch of fetched properties

    dispatch_queue_t queue = dispatch_queue_create("de.berndrabe.dataSource", DISPATCH_QUEUE_CONCURRENT);
    dispatch_group_t outerGroup = dispatch_group_create();

    __block SectionInfo *siPilotAircraft = nil;
    if ([PilotAircraft countOfEntities]) {
        dispatch_group_async(outerGroup, queue, ^{
            NSArray *frPilotAircraft = [PilotAircraft findAll];
            // do some processing an set SectionInfo variable
        });
    }

    __block SectionInfo *siMedicals = nil;

    if ([PilotMedical countOfEntities]) {
        dispatch_group_async(outerGroup, queue, ^{
            NSArray *frPilotMedical = [PilotMedical findAll];
        });
    }

    // more working packets following the same patter

    dispatch_group_wait(outerGroup, DISPATCH_TIME_FOREVER);

    if (siPilotAircraft.countOfRows) {
        [_dataSource addObject:siPilotAircraft];
    }
    if (siMedicals.countOfRows) {
        [_dataSource addObject:siMedicals];
    }
}

return _dataSource;
}

編集: Lets を使用[Entity findAllInContext:privateContext]すると、必要なレコードを取得できますが、1 つのエンティティで障害のある関係にアクセスするときにスタックしてしまいました :(

4

2 に答える 2

0

問題の解決策を見つけました。ここでも(要するに)私が達成しようとしたことです。

NSMutableArray各エントリの dataSource オブジェクトとして機能するタスクのビルドにUITableView は、コア データのフェッチと処理操作が含まれます。完了時に作業を並列化し、結果を追加しますNSMutableArray

dataSource オブジェクトのエントリ数が異なる可能性がある問題

これは私のために働いていました。「NSMutableArray」のカテゴリは、アクセスがシリアル化されていることを確認する便利な方法です。その実装により、可能な限り作業を並列化し、簡単に書くことができます

[自己準備データソース]; [self.tableView reloadData];

一部の作業がまだ進行中であることを心配する必要はありません。

dispatch_queue_t queue = dispatch_queue_create("com.yourdomain.serializedAccess", DISPATCH_QUEUE_CONCURRENT);

- (void)prepareDataSource
{
    [self.dataSource removeAllObjects];

    dispatch_group_t group = dispatch_group_create();

    [self prepareWorkEntry1FromManagedObjectContext:self.privateContext forDataSource:self.dataSource group:group];
    [self prepareWorkEntry2FromManagedObjectContext:self.privateContext forDataSource:self.dataSource group:group];
    [self prepareWorkEntry3FromManagedObjectContext:self.privateContext forDataSource:self.dataSource group:group];

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}

- (void)prepareWorkEntry1FromManagedObjectContext:(NSManagedObjectContext *)context forDataSource:(NSMutableArray *)array group:(dispatch_group_t)group
{
    __weak typeof(self) weakSelf = self;

    dispatch_group_enter(group);
    [context performBlock:^{
    Object *object = nil;
        createObject(object);

    if (object) {
           [array serializedAddObject:object withQueue:weakSelf.queue group:group];
        }
        else {
          dispatch_group_leave(group);
        }
    }];
}


@implementation NSMutableArray (ResourceProtection)

- (void)serializedAddObject:(id)object withQueue:(dispatch_queue_t)queue group:(dispatch_group_t)group
{
    if (group == NULL) {
        dispatch_barrier_async(queue, ^{
            [self addObject:object];
        });
    } else {
        dispatch_barrier_async(queue, ^{
            [self addObject:object];
            dispatch_group_leave(group);
        });
    }
}

@end

編集: ResourceProtection カテゴリに関する限り、確認する必要があります

  1. dispatch_group_enter は、dispatch_group_leave の前に呼び出されます
  2. dispatch_group_enter と dispatch_group_leave のバランスがとれている

ここでは、変更可能なオブジェクトの監視された同期ライター スキームを示します。

于 2013-08-26T16:14:30.000 に答える