I’ve ran into some issues using ^blocks in Objective-C. I’m trying to set an instance variable from within a block – I’ve read through some Apple documentation on the topic, and I feel I have tried everything.
@interface MyClass
{
// I have tried all possible combinations using __weak, __strong and __block.
__weak __block NSMutableArray *filenames;
}
// *.m
static ASIFormDataRequest *g_request = nil;
@implementation MyClass
-(void) funnymethod
{
filenames = [NSMutableArray array];
[filenames addObject:@"This is a string."];
NSLog(@"%@", filenames);
g_request = [InitializerClass initializeRequest];
[g_request setCompletionBlock:^
{
filenames = [NSMutableArray array];
[filenames addObject:@"This is another string."];
NSLog(@"%@", filenames);
}];
[g_object startASynchronous];
}
@end
The code above gives the following output:
( “This is a string.” )
(null)
That sucks. So, I’ve tried different combinations of __weak, __strong and __block – and anything else gives the following output:
( “This is a string.” )
( “This is another string.” )
BUT! There’s a massive but. The completion block is never exited. The activity indicator in the top bar indicating an open connection keeps spinning, and the screen becomes unresponsive.
How can I set the filenames-object from within the block successfully? Thanks in advance.
What the qualifiers do:
__blockthis qualifier allows a closure to modify the value stored in the given variable.__weakis a reference to an object that does not prevent the object from being de-allocated.__strongis a reference to an object that does prevent the object from being de-allocated.What you need to do:
__weakdoesn’t do what you want because it doesn’t prevent your array from being de-allocated after the current scope ends. Since you are making an async call, there is nothing preventing the run-time from reclaiming the memory used by the array before your block is executed.__strongwill retain the object past the end of the current scope. This is what you want.__blockwill allow your block to modify the specified variable, however this isn’t needed when referencing an instance variable sinceselfwill be automatically retained.I think your problem lies here (relevant portions in bold):
Instead of an
NSMutableArray, try using a plainNSArrayusing+ (id)arrayWithObject:(id)anObject.