8

我已经阅读了 Apple 的 Blocks Programming Topics 和我的尽职调查在线搜索,但我仍然不清楚我是否正确实施了我的块。我有一组客户端作为发送 NSNotification 时填充的属性。Clients 用作 tableview 数据源。下面的代码有效,但我很好奇它是否将 self 置于保留周期中。我应该做类似的事情__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

访问 clients 属性没有问题,因为它是一个强(即保留)属性。所以你不需要__block这里。

一个问题可能self是在发送通知时可能不再存在。然后您将访问已释放的对象,应用程序可能会崩溃!为避免这种情况,您应该删除dealloc方法中的观察者。

__block之前id observer绝对是必需的!

编辑:

self在 iOS 5 中,您可以使用弱引用安全地捕获:

__weak id weakSelf = self;

然后在块内您可以安全地使用weakSelf.clients. 当对象被释放时,变量weakSelf 将自动变为nil。

于 2012-08-21T16:14:03.527 回答
3

是的,您有一个保留周期,至少在通知发生之前是这样。当您访问块中的clientsivar 时,该块将保留自身。它将由通知中心的块保留,直到通知发生(因为您在块的末尾删除了观察者)。如果您不希望这样做,您可以使用对 self 的弱引用。

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 回答