In iOS block how to modify variables outside without using __block - ios

I read that if block wants to modify a variable outside, this variable has to be described by using keyword __block since it has to be copied to heap with block itself.
But what if I do not want to use __block and still get to modify the variable, is there a way?
I did some thinking that maybe I can set that variable to global or static instead of an auto one so that it will be stored in static memory area.
Or can I set it to pointer and point to some content which is allocated on heap? I tried this case which didn't work, I would like to know why.

Essentially, in order to avoid losing the variable, block would copy the local variable onto heap if you would like to access and modify the variable. But if you make the variable global or static, which would be stored on global region and you don't need to worry losing it on stack, block wouldn't copy it but is able to modify it directly.
Please correct me if any mistake and I will mark myself answer if there isn't any better one.

Related

Instance variable & properties in blocks

All objects are in the heap, that is obvious, but what about the instance variables?
Do they change the retain count? If yes, can they be directly used and modified in blocks?
I came across a tutorial which says blocks can modify objects that are in the heap. So another question arises: Can we modify a heap object without using
__block before the object type?
You don't need the __block qualifier in order to modify instance variables. You were on the right track in thinking about this. If a thing is on the heap, it's persistent. If it is stack based, like a local variable, it does need to be marked with __block if the block modifies it.

Where should I release static local and global variable with ARC?

I just created a new class in my project, subclass of UITableViewController and noticed that in the method tableView:cellForRowAtIndexPath: template, Apple still provide a static local NSString to use as a cell identifier.
I know that for static global/local variable we need to assign nil cause it's considered as strong.
So I asked myself the question : Where should I assign nil to static global variable ?
And static global variable ?
Thanks for the answers guys
A short answer to the "where should static global variables be released" is "nowhere".
Long answer goes like this: when you make a variable static or global, you want it to exist regardless of any instances of your classes coming into existence or being released. Simply speaking, you want your statics to always be there for you. Therefore, the only reason to release them would be if your program is about to exit. But if your program is exiting anyway, you might as well let the operating system handle the cleanup for you, and forget about releasing your global and static variables.
Note, however, that the use of static and global variables should be an exception, not a norm. You use them for a good reason, and exercise your best judgement to decide what should be static. Moreover, you should avoid referencing collections of non-static variables from static ones through a strong reference, because otherwise you may create hard-to-find memory leaks.
There is nothing wrong with a static local for the NSString used as your cell identifier: it takes very little memory, and it does not grow, so it's not a big deal that it is not released at the end of your program's run.
You don't need to do it, it will never be released and its ok since it is a global.
In ARC will be treated as strong for default and its lifetime it is equal to the application lifetime.
Static strings are a special case, and don't need to be released.
static variable, means it holds a strong reference to the object it points to.
static MyClass *var;
var = [MyClass instance];
Now var always holds strong reference to the above allocated object.so it will never be removed from memory.
But after some condition you no longer need that object,then simply
var =nil would work.
because now var points to nil and no longer points to created object.so that object will be deleted from memory.

Is there an Objective-C property attribute that mimics the functionality of the __block keyword?

I want to make a property that allows a block to update its contents. For a typical variable (i.e. not auto-synthesized, etc), I would prefix the declaration with __block.
Is there a way to make a property that is able to be updated by a block?
Edit: Some answers say just to use the properties setter method. What I actually want to do is add objects to a mutable array, so I don't really want to create a new mutable array and set it back to the property using setProperty: or .property = each time. Is it possible to modify the property without all of these memory allocations?
__block is used to declare local variables that a block might want to change.
Neither are properties local variables, nor is there a need to change a variable when all you want to do is add something to a mutable array. The variable does not change, it's the object's state behind the variable that changes.
This isn't the right way to think about it. You want to modify an object, which has a property. So you capture the object in the block, and call its accessors (setFoo:) to modify the property.
EDIT: From the various edits, you may be confusing how ObjC objects work and how C++ works. ObjC only uses pointers to objects, seldom copies them, and lacks the concept of a const object (there are immutable objects, but it's just because they don't have mutators; you can't const a mutable object like you can in C++).
__block just means "this variable (not the object pointed to by it; this actual variable) should be passed by reference into the block rather than by value)." So when I say:
__block id foo;
this means that the foo pointer itself can be changed. It has nothing at all to do with whether the object pointed to by foo can be mutated. This makes no sense for a global or an ivar. ivars are implicitly struct fields. When you say _ivar inside a block, the compiler implicitly converts this to self->_ivar and then captures self. It does not capture _ivar (since that's just an offset into the self struct). It's better to do the same using accessors, since it's much more explicit what you're doing, and you can use __weak that way.
You use __block when you want to modify a variable within a block; in your case what you want to do is not modifying the variable(it will still point to the same NSMutableArray) but just sending a message to it(addObject:). You don't need __block for that.
There is no need to put anything into a #property declaration. since they can be accessed and modified by blocks without any trouble. According to the documentation:
Within the block object’s body of code, variables may be treated in
five different ways.
You can reference three standard types of variable, just as you would
from a function:
Global variables, including static locals
Global functions (which aren’t technically variables)
Local variables and parameters from an enclosing scope
Blocks also support two other types of variable:
At function level are __block variables. These are mutable within the
block (and the enclosing scope) and are preserved if any referencing
block is copied to the heap.
const imports.
The following rules apply to variables used within a block:
Global variables are accessible, including static variables that
exist within the enclosing lexical scope.
Parameters passed to the block are accessible (just like parameters to a function).
Stack (non-static) variables local to the enclosing lexical scope are
captured as const variables.Their values are taken at the point of
the block expression within the program. In nested blocks, the value
is captured from the nearest enclosing scope.
Variables local to the enclosing lexical scope declared with the
__block storage modifier are provided by reference and so are mutable.
Any changes are reflected in the enclosing lexical scope,
including any other blocks defined within the same enclosing lexical
scope.
Local variables declared within the lexical scope of the block,
which behave exactly like local variables in a function.Each
invocation of the block provides a new copy of that variable. These
variables can in turn be used as const or by-reference variables in
blocks enclosed within the block.

Having trouble understanding Objective-C Block Documentation

I'm currently having trouble understanding the fundamentals of Obj-C blocks and the __block storage type. From the following documentation:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW6
I'm trying to understand the following paragraph and examples:
When a block is copied, it creates strong references to object variables used within the block. If you use a block within the implementation of a method:
If you access an instance variable by reference, a strong reference is made to self;
If you access an instance variable by value, a strong reference is made to the variable.
The following examples illustrate the two different situations:
dispatch_async(queue, ^{
// instanceVariable is used by reference, a strong reference is made to self
doSomethingWithObject(instanceVariable);
});
id localVariable = instanceVariable;
dispatch_async(queue, ^{
/*
localVariable is used by value, a strong reference is made to localVariable
(and not to self).
*/
doSomethingWithObject(localVariable);
});
To override this behavior for a particular object variable, you can mark it with the __block storage type modifier.
My questions:
How exactly is one example "accessed by reference" while the other one is accessed by variable? Why is localVariable "used by value?"
What does the doc mean by "a strong reference is made to self"? Which "self" is it referring to?
If I add the __block storage type to localVariable in the second example, am I wrong to assume that the block closes over the variable, so it keeps it around in heap until block is released? What other things are happening?
Thank you!
How exactly is one example "accessed by reference" while the other one is accessed by variable? Why is localVariable "used by value?"
One way to understand this is the following:
when you use a local variable in a block defined in the method, what happens is that the content of the variable is copied in some block private memory, so that it is available when the block is executed (after the method exits); in this sense we may talk of accessed "by value" (as in: the value is copied); syntactically the compiler doesn't know what the content of localVariable refers to, so its values is treated as such;
when directly accessing instanceVariable in a block defined within a method of a class, the compiler knows that we are accessing the same object that is executing the method and there is not need to copy anything, since the object has a longer lifetime than the method where the block is found; but we need to ensure that the object is still there when the block is executed, so we get a strong reference to it.
Now, as to the use of "by reference": in the first case, you get a copy of the reference to the class member: if you could change its value (but you can't, because the compiler forbids it), you were just modifying a block private copy, so the original object is not affected.
In the second case, you can modify the value of instanceVariable (like in: it was nil and you allocate an object referred through it) and this will affect the object that executed the method were the block is defined.
What does the doc mean by "a strong reference is made to self"? Which "self" is it referring to?
self is the object which is currently executing the method where the block is found. that a strong reference is made only means (in ARC parlance) that the retain count of the object is incremented (to make sure some other entity cannot cause it to be deallocated by releasing it).
If I add the __block storage type to localVariable in the second example, am I wrong to assume that the block closes over the variable, so it keeps it around in heap until block is released? What other things are happening?
Using __block makes the variable be always accessed "by reference", so you can modify them.
This is how they are handled:
__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable’s lexical scope. Thus, the storage will survive the destruction of the stack frame if any copies of the blocks declared within the frame survive beyond the end of the frame (for example, by being enqueued somewhere for later execution). Multiple blocks in a given lexical scope can simultaneously use a shared variable.
As an optimization, block storage starts out on the stack—just like blocks themselves do. If the block is copied using Block_copy (or in Objective-C when the block is sent a copy), variables are copied to the heap. Thus, the address of a __block variable can change over time.

ios geocodeAddressString modify global variable during block

I understand that the call to CLGeocoder geocodeAddressString is asynchronous, with a block passed in to handle the callback at completion time. I also understand that the only variables that are mutable within the block are local __block variables. But I need to store the resulting CLPlacemarks in a global NSMutableArray variable, and I can't work out how that can happen. Any __block variables can only be accessed within the same method, but at the point that they have any value (i.e. within the block) I can't assign any value to the global array. After the block, the __block variables will likely not have any value because of the immediate return when calling the async geocodeAddressString.
How can I store the results of the call, so that they can be used to update a UITableView?
Ok, solved. I was incorrectly deducing (from my reading about blocks) that properties and instance variables could not be modified within the scope of a block. In my case, the reason I couldn't modify my iVar array was that I hadn't alloc/init'ed it. Once I did that, I was able to assign values and see them outside of the block e.g. in my cellForRowAtIndexPath method of my table view.
Apologies to anyone who may have been misled by my initial assumptions! For the record, I do think that the text on the Apple docs re blocks & variables here is a bit misleading...the only variables that it mentions as being mutable are the __block function-level variables, whereas it says all others "can be accessed" which I took as meaning "read-only" (I know that both getters and setters are accessors, but the context was confusing).

Resources