Objective-C access to properties inside a block

I read "Apple Blocks Programming Topics" and my search on the Internet, but I'm still unclear if I am implementing my blocks correctly. I have an array of clients as a property that populates when sending NSNotification. Clients are used as a table data source. The code below works, but I'm curious if it puts itself in a save loop. Should I do something like __block id theClients = self.clients; and then reference theClients inside the block?

@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]; }]; 
+8
ios objective-c objective-c-blocks
source share
2 answers

There is no problem accessing the property of clients, as it is strong (i.e., saved). So here you do not need __block .

One problem may be that self may not exist anymore when sending a notification. Then you will gain access to the remote object, and the application may work! To avoid this, you must remove the observer in the dealloc method.

Be sure to __block to id observer !

EDIT:

In iOS 5, you can safely grab self using a weak link:

 __weak id weakSelf = self; 

Then inside the block you can safely use weakSelf.clients . The weakSelf variable will automatically turn to nil when the object is freed.

+8
source share

Yes, you have a save cycle, at least until a notification appears. When you access clients ivar in a block, the block will save itself. It will be saved by the block in the notification center until a notification occurs (since you delete the observer at the end of the block). If this is undesirable in your case, you can use a weak link to yourself.

 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]; }]; 

I see no reason why you need a __block qualify observer .

It is also not clear that you are getting something from using a block-based API. If you don't want to worry about a potential hold cycle, you can simply use addObserver:selector:name:object: and put your recall body in an instance method.

+3
source share

All Articles