8

Appleのブロックプログラミングトピックとオンライン検索のデューデリジェンスを読みましたが、ブロックを正しく実装しているかどうかはまだわかりません。NSNotificationが送信されたときに入力されるプロパティとしてクライアントの配列があります。クライアントはテーブルビューデータソースとして使用されます。以下のコードは機能しますが、それが自己を保持サイクルに入れているのかどうか興味があります。私は次のようなことをしてから、ブロック内__block id theClients = self.clients;を参照する必要がありますか?theClients

@property (strong, nonatomic) NSMutableArray *clients;

NSNotificationCenter *notifyCenter = [NSNotificationCenter defaultCenter];
__block id observer = [notifyCenter addObserverForName:queryHash
                                                object:nil
                                                 queue:[[NSOperationQueue alloc] init]
                                            usingBlock:^(NSNotification* notification){
                                                // Explore notification

    if ([[notification.userInfo objectForKey:kdatasetReturnKey] objectAtIndex:0]) {
        NSArray *rows = [[notification.userInfo objectForKey:kdatasetReturnKey] objectAtIndex:0];
        if (self.clients)
        {
            self.clients = nil;
        }
        self.clients = [[NSMutableArray alloc] initWithCapacity:rows.count];
        for (NSDictionary *row in rows) {
            [self.clients addObject:row];
        }
    } else {
        NSLog(@"CLIENTS ERROR Returned: %@",[notification.userInfo objectForKey:kerrorReturnKey]);
    }

    [[NSNotificationCenter defaultCenter] removeObserver:observer];
}];
4

2 に答える 2

8

クライアント プロパティは強力な (保持されている) プロパティであるため、アクセスに問題はありません。したがって、ここは必要ありません__block

1 つの問題はself、通知が送信されたときにもう存在しない可能性があることです。次に、割り当てが解除されたオブジェクトにアクセスすると、アプリがクラッシュする可能性があります! これを避けるには、deallocメソッドでオブザーバーを削除する必要があります。

__blockid observer必ず必要です!

編集:

selfiOS 5では、弱参照を使用して安全にキャプチャできます。

__weak id weakSelf = self;

その後、ブロック内で安全に使用できますweakSelf.clients。オブジェクトの割り当てが解除されると、変数weakSelfは自動的にnilになります。

于 2012-08-21T16:14:03.527 に答える
3

はい、少なくとも通知が発生するまで、保持サイクルがあります。ブロック内の ivar にアクセスするclientsと、ブロックは自己を保持します。通知が発生するまで、通知センターのブロックによって保持されます (ブロックの最後でオブザーバーを削除するため)。あなたのケースでそれが望ましくない場合は、自己への弱参照を使用できます。

NSNotificationCenter *notifyCenter = [NSNotificationCenter defaultCenter];
__weak id weakSelf = self;
id observer = [notifyCenter addObserverForName:queryHash
                                        object:nil
                                         queue:[[NSOperationQueue alloc] init]
                                    usingBlock:^(NSNotification* notification) {
    if (weakSelf) {                                
        if ([[notification.userInfo objectForKey:kdatasetReturnKey] objectAtIndex:0]) {
            NSArray *rows = [[notification.userInfo objectForKey:kdatasetReturnKey] objectAtIndex:0];
            if (weakSelf.clients)
            {
                weakSelf.clients = nil;
            }
            weakSelf.clients = [[NSMutableArray alloc] initWithCapacity:rows.count];
            for (NSDictionary *row in rows) {
                [weakSelf.clients addObject:row];
            }
        } else {
            NSLog(@"CLIENTS ERROR Returned: %@",[notification.userInfo objectForKey:kerrorReturnKey]);
        }
    }    
    [[NSNotificationCenter defaultCenter] removeObserver:observer];
}];

__blockあなたが資格を得る必要がある理由がわかりませんobserver

また、ここでブロックベースの API を使用して何かを得ているかどうかも明らかではありません。潜在的な保持サイクルについて心配したくない場合はaddObserver:selector:name:object:、通知コールバックの本体を使用してインスタンス メソッドに入れることができます。

于 2012-08-22T17:14:33.053 に答える