Accessing properties from the ^ block causes silly behavior

I ran into some problems using ^ blocks in Objective-C. I'm trying to set an instance variable from within a block - I've read Apple's documentation on this topic and I feel like I've 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 above code gives the following output: ("This is a string"). (Zero)

It sucks. So, I've tried different combinations of __weak, __strong and __block - and everything else gives the following result: ("This is a string"). ("This is another line"). BUT! There is massive, but. The completion block never exits. The activity indicator on the top bar showing an open connection continues to rotate and the screen becomes unresponsive.

How can I successfully set filenames from a block? Thanks in advance.

+3


source to share


1 answer


What qualifiers do:

__block

this qualifier allows the closure to change the value stored in the given variable.

__weak

is an object reference that does not prevent the object from being thrown.

__strong

is an object reference that prevents the object from being selected.

What you need to do:

__weak

doesn't do what you want because it doesn't interfere with your allocated array after the end of the current scope. Since you are making an asynchronous call, there is nothing stopping the runtime from reclaiming the memory used by the array before your block is executed.

__strong

will keep the object outside the current area. Is this what you want.



__block

will allow your block to modify the specified variable, however this is not required when referencing an instance variable as it self

will be automatically saved.

In a default reference counting environment, when you reference an Objective-C object within a block, it persists. This is true even if you are simply referring to an object instance variable. object variables marked with the __block type modifier, however, are not saved.

Note. In a garbage collection environment, if you apply both __weak and __block modifiers to a variable, then the block does not guarantee that it will be saved. If you use a block as part of a method implementation, the rules for managing the memory of object instance variables are more subtle:

If you access an instance variable by reference, self is retained,

I think your problem lies here (relevant parts in bold ):

You can specify that the imported variable can be changed, i.e. read-write using the __block modifier. __block storage is similar to, but does not exclude, case, auto, and static storage types for local variables.

__ Block variables live in storage, which are shared between the lexical scope of the variable and all declared blocks and block copies, or created within the lexical scope of the variables. Thus, withstand the destruction of the stack frame if any copies of the blocks declared in the frame go out of frame (for example, by being placed somewhere for later execution). multiple blocks in a given lexical scope can share a common variable at the same time.

As an optimization, block storage starts on the stack - just like blocks do themselves. If a block is copied using Block_copy (or in Objective-C when a block is sent as a copy) the variables are copied to the heap. Thus, the address of the __block variable may change over time.

There are two additional restrictions on __block variables: they cannot be variable-length arrays, and they cannot be structures that contain C99 variable-length arrays.

Instead, NSMutableArray

try a simple NSArray

one using

+ (id)arrayWithObject:(id)anObject

...

+4


source







All Articles