accessing properties from blocks, Objective C - objective-c

Hi I am trying to use queues and blocks to Multithread but I am having troubles accessing properties from these blocks. When I use NSLog to print the value of self.photoArray I get null. Can someone explain what I did wrong? I have tried This
dispatch_queue_t downloadQueue = dispatch_queue_create("flickrDownload", NULL);
dispatch_async(downloadQueue, ^{
NSArray* photos = [FlickrPhotoSort sortTopPlaces];
dispatch_async(dispatch_get_main_queue(), ^{
self.photoArray = photos; });
});
dispatch_release(downloadQueue);
and this which doesnt use main queue.
dispatch_queue_t downloadQueue = dispatch_queue_create("flickrDownload", NULL);
dispatch_async(downloadQueue, ^{
NSArray* photos = [FlickrPhotoSort sortTopPlaces];
self.photoArray = photos;
});
dispatch_release(downloadQueue);
Here is the setter of photoArray
-(void) setPhotoArray:(NSArray *)photoArray{
if(!_photoArray) _photoArray = [[NSArray alloc] initWithArray:photoArray];
else
_photoArray = photoArray;
}
I am following the online stanford courses and the teacher simply called the property like this and it seems to work
dispatch_queue_t downloadQueue = dispatch_queue_create("flickr downloader", NULL);
dispatch_async(downloadQueue, ^{
NSArray *photos = [FlickrFetcher recentGeoreferencedPhotos];
dispatch_async(dispatch_get_main_queue(), ^{
self.navigationItem.rightBarButtonItem = sender;
self.photos = photos;
});
});
dispatch_release(downloadQueue);

When I use NSLog to print the value of self.photoArray I get null.
The asynchronously running [FlickrPhotoSort sortTopPlaces] is probably still running when you hit the log statement and the property just hasn't been set, yet.

Since properties invoke a method call I have had no issue setting them within a block. __block only adds visibility to a variable outside the scope of the block - so that changes to a variable from within the block are seen outside the block's scope. It has no effect on properties only on using vars directly in the block (where they be ivars or not.) properties are not ivars they are explicit method calls to a class which sets an ivar outside the scope of the block.
You should be retaining the photo array in the setter though - the array will be released at the end of the block otherwise. I have tons of code setting properties from within blocks with no issues.

Use the keyword __block for iVars in blocks. This makes sure, that the property stays in memory. If you use ARC and pre 5.0 use __unsafe_unretained else __weak
__block NSArray *bPhotoArray = self.bPhotoArray;
dispatch_async(downloadQueue, ^{
NSArray* photos = [FlickrPhotoSort sortTopPlaces];
bPhotoArray = photos;
});

Related

"Capturing 'self' strongly in this block is likely to lead to a retain cycle" using Reachability

I'm trying to edit a variable inside the Reachability block using Objective-C, this is the code:
- (void)testInternetConnection
{
internetReachableFoo = [Reachability reachabilityWithHostname:#"www.google.com"];
// Internet is reachable
internetReachableFoo.reachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Connessione ad Internet disponibile");
checkConnection = YES;
if(!lastConnectionState)
{
lastConnectionState = YES;
if(doItemsDownload)
[self displayChoice];
}
});
};
// Internet is not reachable
internetReachableFoo.unreachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Connessione ad Internet non disponibile");
checkConnection = NO;
lastConnectionState = NO;
});
};
[internetReachableFoo startNotifier];
}
Where checkConnection; & lastConnectionState; are 2 bool declared on my #interface;
The problem is that accessing these variables and calling [self displayChoice]; inside this block gives me the warning: Capturing 'self' strongly in this block is likely to lead to a retain cycle
How can I possibly avoid this error?
I tried declaring a WeakSelf and declaring self but I don't know how to do it for the bool variables
Capturing self strongly in a block is not always bad. If a block is being executed right away (UIView animate block for example) there is generally no risk.
The problem arises when self captures a block strongly and the block in turn captures self strongly. In this case self retains the block and the block retains self so neither can be released --> retain cycle!
To avoid this you need to capture self weakly in the block.
__weak typeof(self) = self; // CREATE A WEAK REFERENCE OF SELF
__block BOOL blockDoItemsDownload = doItemsDownload; // USE THIS INSTEAD OF REFERENCING ENVIRONMENT VARIABLE DIRECTLY
__block BOOL blockCheckConnection = checkConnection;
internetReachableFoo.reachableBlock = ^(Reachability*reach)
{
// Update the UI on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Connessione ad Internet disponibile");
blockCheckConnection = YES;
if(!lastConnectionState)
{
lastConnectionState = YES;
if(blockDoItemsDownload) // Use block variable here
[weakSelf displayChoice]; // Use weakSelf in place of self
}
});
};
There is a cocoapod called libextobjc and what it allows you to do is quickly and cleanly weakify and strongify objects.
#weakify(self)
[someblock:^{
#strongify(self)
}];
As long as you handle self you should be ok. I'm not 100% sure the BOOL values aren't an issue but I think you could do something like this:
BOOL x = YES;
#weakify(self, x)
[someblock:^{
#strongify(self, x)
}];

Instance variables and threading with GCD

I recently added threading to an app so that network requests are not blocking the UI. On doing this, I discovered that I could no longer set my instance variable the same way as I had before implementing threading. My instance variable is a property declared as follows:
#property (nonatomic, strong) NSMutableArray *currentTopPlaces;
Here is how I incorrectly set my instance variable self.currentTopPlaces:
dispatch_queue_t downloadQueue = dispatch_queue_create("Flickr Top Places Downloader", NULL);
dispatch_async(downloadQueue, ^{
__block NSArray *topPlaces = [FlickrFetcher topPlaces];
dispatch_async(dispatch_get_main_queue(), ^{
self.tableRowCount = [topPlaces count];
[[self currentTopPlaces] setArray:topPlaces];
});
Using [self currentTopPlace] setArray:topPlaces] worked fine in the blocking version, before I started using GCD.
Now, I must set it like so for things to work correctly:
dispatch_queue_t downloadQueue = dispatch_queue_create("Flickr Top Places Downloader", NULL);
dispatch_async(downloadQueue, ^{
__block NSArray *topPlaces = [FlickrFetcher topPlaces];
dispatch_async(dispatch_get_main_queue(), ^{
self.tableRowCount = [topPlaces count];
self.currentTopPlaces = topPlaces;
});
Can someone explain to me the difference between using:
[[self currentTopPlaces] setArray:topPlaces];
and:
self.currentTopPlaces = topPlaces;
Specifically, why the "setArray" call did not work in a threaded block?
I thought dot notation in Objective-C is syntactic sugar and not mandatory. I would like to know the "non-sugared" way to achieve the same behavior.
[self currentTopPlaces] and self.currentTopPlaces are in fact identical, but
[self.currentTopPlaces setArray:topPlaces]; // (1)
self.currentTopPlaces = topPlaces; // (2)
are not. (1) replaces all elements of self.currentTopPlaces with those from topPlaces. (2) assigns a new value to self.currentTopPlaces (releasing the old value if it was not nil).
A difference occurs if self.currentTopPlaces is nil: (1) does nothing, because the setArray: method is sent to nil. (2) assigns a new value to self.currentTopPlaces.
Btw: The __block modifier is not necessary in your code, because the block will not change the value of topPlaces.
[[self currentTopPlaces] setArray:topPlaces];
self.currentTopPlaces = topPlaces;
These are two entirely different expressions. The first is as written, the second would be:
[self setCurrentTopPlaces:topPlaces];
If you want to do the first one with dot notation, it would be:
self.currentTopPlaces.array = topPlaces;

Memory management with block and ARC, leak?

I need to know if I do it correctly. The application is running OK but I'm not sure I get the lifecycle correctly (leak ?).
Note: Instrument see no leak.
The code of a method aaa: of some class A:
- (void) aaa {
NSString *path = ...something...;
NSBlockOperation* theOp = [NSBlockOperation blockOperationWithBlock: ^{
// using path
[self somethingElseWith:path];
}];
[self.aQueue addOperation:theOp];
}
So I create a block to put on aQueue (NSOperationQueue*). The goal is to offload from the main thread the long running somethingElseWith: method, so that the GUI continue to be responsive.
Inside the block I reference the local var "path" that will be out of scope at the end of the aaa: method.
If I read the doc correctly, the block will do a retain on 'path'. But is ARC inserting a release at the end of this block implicitly ? Would be logical and nice.
Or should I declare 'path' as __block and assign it to nil at the end of my block ? (manual...)
Not sure I understand how to use __weak in this context.
The path variable is fine. You may however need to avoid a retain cycle by using a weak reference to self. If aQueue is a strong reference there may be a retain cycle causing self never to be released.
Solution:
- (void) aaa {
NSString *path = ...something...;
__weak id self_ = self;
NSBlockOperation* theOp = [NSBlockOperation blockOperationWithBlock: ^{
// using path
[self_ somethingElseWith:path];
}];
[self.aQueue addOperation:theOp];
}
Make sure the operation does not get called after the class should no longer exist.
The block will automatically handle memory management for any locals from the enclosing scope. You don't have to worry about retain/release pairs in this case. Note, though that path will be const within the block's scope. If you need pathto be mutable within the block, use the __block attribute.
The different ways a block handles variables is described in detail here: Blocks and Variables

Blocks and Variables

At the moment I explore blocks opportunities, I read more then ten times apples docs) but i cant understand blocks behaviour in blogs examples and in my code. I know about __block modifier. So please look at few my examples, and say why it work or not:
1)Not working. Need __block, because I want to modified object.And self retained(correct?) and in blogs I'm frightened by retain cycle of self. Does it is?
NSDictionary *result = nil;
dispatch_async(queue, ^{
result = [self sendRequest:apiRequest];
});
2)Not working. I dont understand about variable scope of dispatch_async(dispatch_get_main_queue(), ^{});. Does it see all local variables in main thread or it is separate block from main thread, but exicuted in main thread? Like dispatch_async(dispatch_get_main_queue()^{}); copies all local variables in dispatch_async(queue,^{}); and switches semaphore to main thread.
NSDictionary *result = nil;
dispatch_async(queue, ^{
NSDictionary *data = [self sendRequest:apiRequest];
dispatch_async(dispatch_get_main_queue(), ^{
result=[data retain];
});
});
3)And examples from blogs and stanford's course that particularly muddle me, because they work.
- (void)viewWillAppear:(BOOL)animated
{
dispatch_queue_t downloadQueue = dispatch_queue_create(“image downloader”, NULL);
dispatch_async(downloadQueue, ^{
NSData *imageData = [NSData dataWithContentsOfURL:networkURL];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
self.imageView.image = image;
self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
 self.scrollView.contentSize = image.size;
});
});
dispatch_release(downloadQueue);
}
I dont understand, because first they dont mention about __block for self in the articles and the lessons, second this code modified variables, but through properties and complier doesn't swear that variables arent assignable and properties change reference, not value. Final it works. Thanks in advance.
Old question, but I feel like new readers might benefit from a more precise answer than the current one:
1) result is a pointer to an object, not an object itself. Prepending __block is necessary because that pointer is assigned to within the block. Modifying objects pointed to by pointer variables outside of the block is not the problem, e.g.
NSMutableDictionary* result = [NSMutableDictionary new];
and then modifying the object within the block via [result setObject...] would be fine. And that's the reason why 3) works: Only variables of the object pointed to by self are being modified. The pointer self is never assigned to.
Regarding retainment under ARC of the objects referenced by the block, see e.g.:
ARC with blocks and retain cycles
ARC, Blocks and Retain Cycles
blocks and ARC - copy or crash with release build (caused by optimization level)
1) Yes you'd need to declare:
__block NSDictionary *results = nil;
If you're using ARC it should automatically take care of retaining and releasing the results object. If not using ARC, then do a retain as the first thing you do and a release as the last thing you do in the block.
2) A block should have visibility of all variables/objects available to it's parent's scope. So in a method you should be able to see all local variables to that method and the object which that method belongs to (as self).
3) Not too sure about this one. Variables do go away once you leave the function/method (which will be as so as most blocks have been called, rather than finished executing), where as anything that is part of self won't. Maybe that has something to do with it.

Calling [self methodName] from inside a block?

I've just run into blocks and I think they are just what I'm looking for, except for one thing: is it possible to call a method [self methodName] from within a block?
This is what I'm trying to do:
-(void)someFunction{
Fader* fader = [[Fader alloc]init];
void (^tempFunction)(void) = ^ {
[self changeWindow:game];
//changeWindow function is located in superclass
};
[fader setFunction:tempFunction];
}
I've been searching for a couple of days and I can't find any evidence that this is possible.
Is this at all possible, or am I trying to use blocks for something they aren't meant for?
The reason I'm using blocks is that I've created a Fader class, and I want to store a block for it to execute when it finishes fading out.
Thank you
EDIT:
Okay, I added in the suggestion, but I'm still getting an EXC_BAD_ACCESS error...
-(void)someFunction{
Fader* fader = [[Fader alloc]init];
__block MyScreen* me = self;
void (^tempFunction)(void) = ^ {
[me changeWindow:game];
//changeWindow function is located in superclass
};
[fader setFunction:tempFunction];
[fader release];
}
Maybe I'm not allowed to give fader the function...?
Yes, you can do this.
Note, however, that the block will retain self. If you end up storing this block in an ivar, you could easily create a retain cycle, which means neither would ever get deallocated.
To get around this, you can do:
- (void) someMethodWithAParameter:(id)aParameter {
__block MySelfType *blocksafeSelf = self;
void (^tempFunction)(void) = ^ {
[blocksafeSelf changeWindow:game];
};
[self doSomethingWithBlock:tempFunction];
}
The __block keyword means (among other things) that the referenced object will not be retained.
The accepted answer is outdated. Using __block in that case can cause errors!
To avoid this problem, it’s best practice to capture a weak reference to self, like this:
- (void)configureBlock {
XYZBlockKeeper * __weak weakSelf = self;
self.block = ^{
[weakSelf doSomething]; // capture the weak reference
// to avoid the reference cycle
}
}
Please, look at Apple Documentation - Avoid Strong Reference Cycles when Capturing self
for more details.
__block CURRENTViewController *blocksafeSelf = self;
[homeHelper setRestAsCheckIn:strRestId :^(NSObject *temp) {
[blocksafeSelf YOURMETHOD:params];
}];
Is it possible to call a method [self methodName] from within a block?
Yes, why not. If your tempFunction is an instance method, you can do it. The called method should be accessible is the only restriction.
Consider this (which I think is the best practice)
#implementaion ViewController
- (void) viewDidLoad {
__weak typeof(self) wself = self;
[xxx doSomethingUsingBlock: ^{
__strong typeof(wself) self = wself;
[self anotherMessage];
}];
}
#end
Moreover, You can define wrapper macros.
#define MakeWeakSelf __weak typeof(self) wself = self
#define MakeStrongSelf __strong typeof(wself) self = wself
I wonder whether you [fader setFunction:tempFunction]; then is synchronous or asynchronous.
blocks push onto stack.so in MRR,if you don't retain it,it will pop off.
-(void)someFunction{
Fader* fader = [[Fader alloc]init];
void (^tempFunction)(void) = ^ {
[self changeWindow:game];
//changeWindow function is located in superclass
};
[fader setFunction:tempFunction];
//if the tempFunction execute there will be right.
}//there the tempFunction pop off
//....some thing go on
//execute the tempFunction will go wrong.