Objective-C: initialization of blocks stored in collections - ios

I read this article : Storing Blocks in an Array and want to clarify some moments.
Consider next code:
NSMutableArray* storage1;
NSMutableArray* storage2;
-(id)init{
self=[super init];
if(self){
storage1=[NSMutableArray new];
storage2=[NSMutableArray new];
}
return self;
}
-(void) f1{
__block int x=1;
dispatch_block_t b0=^{
i++;
i++;
sleep_indefinitely
};
[storage1 addObject:b0];
dispatch_async(global_concurrent_thread,b0());
[storage2 addObject:[storage1 objectAtIndex:0]];
}
The question is: will storage2 contain block with updated value of i or not? Is it necessary to copy block before storing it in collection if I want to have 2 independent instances? And if it is then how the variables with __block specifier are initialized during copying?

The answers to your questions lie in understanding lifetime – every variable and object created in a program has a lifetime which determines how long the variable or object survives. The __block attribute modified the lifetime of the variable it is applied to, potentially increasing it.
To the gory details (there will be the dead carcases of variables and objects littering the answer ;-)) starting at the beginning with a variable declared within a simple function:
int answer1(void)
{
int x = 21; // variable x is created with a fixed lifetime of the end of the function
// invocation – each function invocation creates a new distinct variable x
return x * 2;
// end of the function, x dies
}
A call to answer1() returns 42. During that call a variable is created and destroyed, after the call it no longer exists. Every call to answer1() creates a new distinct variable, and then destroys it when the invocation returns.
The lifetime of standard local variables is tied to the function, method or block statement they are created in.
Dynamically created objects have lifetimes not limited by the function/method/block statement they are created it but live as long as there exists a strong reference to them.
int answer2(void)
{
NSMutableArray *x = [NSMutableArray new]; // variable x is created with a fixed lifetime
// of the end of the function
// an NSMutableArray object is created with an
// indeterminate lifetime – it will live as long
// as there exists a strong refernece to it
// a strong reference to this object is stored in x
[x addObject:#21];
return [x[0] intValue] * 2;
// end of the function, x dies
// as x contained the only strong reference to the array object
// so that object is now longer wanted and can now be culled
// – its lifetime is now over as well
}
A call to answer2() also returns 42. Important: the array object created during the call has died not because the call has returned, the reason for variable x's demise, but because there is no longer any strong reference to it stored anywhere – unwanted it is culled.
Now let's look at blocks. On creation a block object contains copies of the values in any local variables it references:
typedef int (^IntBlock)(void); // for convenience
int answer3(void)
{
int x = 20; // variable x is created with a fixed lifetime of the end of the function
IntBlock b1 = ^{ return x; }; // variable b1 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a copy of the *value* in x,
// i.e. 20
x += 2;
IntBlock b2 = ^{ return x; }; // variable b2 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a copy of the *value* in x,
// i.e. 22
return b1() + b2();
// end of function
// x, b1 and b2 all die
// as b1 & b2 contained the only strong references to the two block objects
// they can now be culled – their lifetimes are over
}
A call to answer3() returns 42 (what a surprise ;-)). During the invocation of answer3() two distinct blocks are created and though the code bodies are the same they contain different values for x.
And finally we come to __block, the lifetime enhancing attribute for local variables, any local variable blessed with this attribute at birth is not consigned to die at the end of its creating function/method/block statement:
typedef void (^VoidBlock)(void);
IntBlock answer4(void)
{
__block int x = 42; // variable x is created with a lifetime the longer of:
// * the lifetime of the current invocation of answer4()
// * the lifetime of the longest living block which
// uses x
VoidBlock b1 = ^{ x = x / 2; }; // variable b1 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a reference to the *variable* in x
IntBlock b2 = ^{ return x * 2; }; // variable b2 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a reference to the *variable* in x
b1(); // call b1(), alters the value in x
return b2; // return a reference to the second block
// end of function
// b1 dies
// as b1 contained the only strong reference to the first block it can now be culled
// b2 also dies
// however a reference to the block it referenced is returned by the function, so
// that block lives
// the returned block references x so it to lives
}
void test4(void)
{
IntBlock b1 = answer4(); // a reference to a block is returned by answer4() and stored in b1
NSLog(#"The answer is %d", b1()); // outputs 42
// end of function
// b1 dies
// as b1 contained the onlyt surviving reference to the block returned by answer4()
// that block may now be culled
// as that block contains the only surviving reference to the variable x
// that variable may now be culled
}
A call to test4() outputs The answer is 42. Note how there is only one x shared by both b1 & b2.
Further note how the lifetime of local variable x is extended past the invocation of answer4() as it is captured by the block object that is returned. However once the block object's time is up x is culled – like an object its lifetime is dependent on something holding an interest in it.
Is it a coincidence that the conditions on the lifetime of x are rather similar to that on an object? No, the next example is effectively (i.e. precise details will differ, the visible behaviour is the same) how the compiler handles answer4():
#interface LifetimeExtenderObject5 : NSObject
#property int x;
#end
#implementation LifetimeExtenderObject5
#end
IntBlock answer5(void)
{
LifetimeExtenderObject5 *leo = [LifetimeExtenderObject5 new]; // variable leo is created with a lifetime of
// the end of the function
// a LifetimeExtenderObject5 is created with
// an indeterminate lifetime and a reference
// to it stored in leo
leo.x = 42;
VoidBlock b1 = ^{ leo.x = leo.x / 2; }; // variable b1 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a copy of the *value* in leo
// this value is a strong reference to the created
// LifetimeExtenderObject5, so now there are two strong
// references to that object
IntBlock b2 = ^{ return leo.x * 2; }; // variable b2 is created with a fixed lifetime of the end
// of the function
// a block object is created with an indeterminate lifetime
// and a strong reference to it is stored in b1
// the block object contains a copy of the *value* in leo
// this value is a strong reference to the created
// LifetimeExtenderObject5, so now there are three strong
// references to that object
b1(); // call b1(), alters the value in x
return b2; // return a reference to the second block
// end of function
// leo dies, but the LifetimeExtenderObject5 object it references has other strong
// references so it lives
// b1 dies
// as b1 contained the only strong reference to the first block it can now be culled
// that block contained a string reference to created LifetimeExtenderObject5 object,
// but there are still remaining strong references to that object so it lives
// b2 also dies
// however a reference to the block it referenced is returned by the function, so
// that block lives
// that block contains a strong reference, the last one, to the created
// LifetimeExtenderObject5 object, so it still lives.
}
void test5(void)
{
IntBlock b1 = answer5(); // a reference to a block is returned by answer5() and stored in b1
NSLog(#"The answer is %d", b1()); // outputs 42
// end of function
// b1 dies
// as b1 contained the only surviving reference to the block returned by answer5()
// that block may now be culled
// as that block contains the only surviving reference to the created
// LifetimeExtenderObject5 object that object may now be culled
}
You asked:
Is it necessary to copy block before storing it in collection if I want to have 2 independent instances?
The above hopefully tells you that copying won't get you two independent instances of the captured __block variable. For that you need distinct __block variables to capture, which you get from distinct invocations of the function they are declared in. Every call to answer4() above returns a block which has captured a distinct/"independent instance" of the __block attributed variable x.
HTH more than it confuses!

First, in your code there is only one block instance created per call of f1, as there is only one ^{ } expression which is only run once. Even if there were multiple blocks, created in a particular call of f1, they would reference the same x variable, since it is a __block variable, so it is captured by reference. Also, copying a block does not create multiple instances of the block -- it simply moves the block from stack to the heap if it is not already on the heap.
It is necessary to copy the block before storing it in the collection, not because it will create multiple instances of the block (it doesn't), but because a block by default starts out on the stack as an optimization. If you will be storing it in a place that will outlive the scope where the block was created, you must "copy" the block which moves it from the stack to the heap (if it isn't there already). (The collection will "retain" the object that it needs to store, but retaining a block doesn't move it from the stack to the heap.) However, recent versions of the Clang compiler, when compiling in ARC, will implicitly add a copy when you pass a variable of block type into a function parameter of non-block object type (e.g. here, -[NSMutableArray addObject:], which takes type id), so you don't have to do it yourself.

First, The block store in both storage1 and storage2 is same block instance. Then, block store in storage2 can update i variable.
Second, If you want to have 2 independent block instances. You must call Block_copy function.
Third, When you copy block, variable with __block specifier is same in both block. Impossible copy variable with __block specifier.
Final, If you copy block also, 2 block will can update variable i.
According Apple document: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW6
__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.

Related

Swift C callback - takeUnretainedValue or takeRetainedValue for Swift class pointer

I have several UIView or UITableViewCell. Inside I have C callback, for example:
CCallback(bridge(self),
{(observer, data) -> Void in
let mySelf = Unmanaged<DetailedView>.fromOpaque(observer!).takeRetainedValue()
mySelf.fillLoadedData(data: data)
});
Somewhere else
func bridge<T : AnyObject>(_ obj : T) -> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
}
In C:
void CCalback(void * classPtr, void(*callback)(void *, MyData)){
//fill data
callback(classPtr, data)
}
Should I use takeUnretainedValue or takeRetainedValue in closure? As far as I understand this, retained will increase objects reference count, so it wont be auto-destructed? Otherwise, if I use takeUnretainedValue, if self is auto-released, this will crash, so using takeRetainedValue will prevent it. Am I correct?
An object pointer can be converted to a Unsafe(Mutable)RawPointer (the Swift
equivalent of the C void *) with or without retaining the object:
let ptr = UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
// Does not retain `obj`
let ptr = UnsafeMutableRawPointer(Unmanaged.passRetained(obj).toOpaque())
// Retains `obj`
The conversion back to an object pointer (often done in a callback
function called from C) can be with or without consuming a retain:
let obj = Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
// Does not consume a retain
let obj = Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()
// Consumes a retain
If the lifetime of obj is guaranteed while the callback is active
then the easiest way is to use the "unretained" conversions in both directions. You are responsible for retaining obj while the
callback is active, e.g. by unregistering the callback before obj
is deinitialized.
The alternative is to use passRetained() to convert obj to
a pointer. This retains the object and therefore keeps it "alive".
The callback can still use the "unretained" conversion to convert
the pointer to an object pointer, without decreasing the retain count.
But there must be exactly one takeRetainedValue() call to consume the
retain. After that, the object can be destroyed if there are no
other references to it.
More generally, each call to passRetained(obj) increases the retain
count and each call to takeRetainedValue() decreases it, so they must be properly balanced.

Will returning nil in init cause a memory leak?

Will returning nil under ARC in init lead to memory leak, when [super init] was already called, but then returned nil? Is this a legit usage?
- (id)init {
self = [super init];
if (self) {
...
return nil;
...
}
return self;
}
First of all: For Qs referring to ARC never read Apple's documentation, but clang's.
Apple's documentation simply conceals (concealed?) the execution of -init and have wrong examples like that:
id ref = [[Class alloc] init]
You will find there a statement like "+alloc transfers ownership". This is at least misleading, because the return value auf -init and not the return value of +alloc is stored.
clang's documentation is better and more precise by far. Basically they say, that +alloc is an ownership transfer and that -init is ownership consuming and ownership transferring.
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics-of-init
Methods in the init family implicitly consume their self parameter and return a retained object.
So let's have a look to the usual code:
id ref = [Class alloc];
// ref is strong: RC is +1;
id ref = [ref init];
// Three things happen her:
// 1. -init is executed
// 2. The new value is stored
// 3. The old value of ref is lost
// 1. -init is executed
// self is (silently) passed to the receiver
- (id)init
{
// Since self is strong (+1), RC is +2 now
// Since -init is ownership consuming (-1), RC is +1 now
…
return self;
// Since -init is ownership transferring (+1), RC is +2 now
}
// 2. The new value is stored
// The value comes from an ownership transfer method, so the assignment to strong ref is neutral (0), RC is still +2
// 3. The old value is lost (-1), RC is +1
The result is that the object has an RC of +1 and you have one strong reference to it in that code area. Everything is fine. (Of course there is a high potential for optimization, because in most cases neither self nor ref is changed, but let's keep on the regular track.)
Let's change self inside -init:
id ref = [Class alloc]; // Ownership transfer. RC is +1;
id ref = [ref init];
// Three things happen her:
// 1. -init is executed
// 2. The new value is stored
// 3. The old value of ref is lost
// 1. -init is executed
// self is (silently) passed to the receiver
- (id)init
{
// Since self is strong (+1), RC is +2 now
// Since -init is ownership consuming (-1), RC is +1 now
// Let's return nil as in your example
return nil;
// Because nil is returned, virtually the RC of nil is increased. self's RC == +1 is unchanged.
}
// 2. The new value is stored
// The new value is nil.
// However the value comes from an ownership transfer method, so the assignment to strong ref is neutral (0), RC is still +1
// 3. The old value is lost (your old ref and the self while executing -init) (-1), RC is 0
// The old object is dealloced, if you do not have another ref to it. Nothing leaks.
I just checked that in the Instruments - no memory leaks

Modifying global variables in Objective-C blocks

So I have an instance function that takes in an NSInteger as a parameter; and in the function, I have a block. I need to modify the NSInteger that gets passed into the function. But it isn't a __block type. How should I go about doing that?
The original function is too complicated so I'll just put a simplified version here...
//#interface
#property(nonatomic) NSInteger input;
...
//#implementation
[self doThis:self.input];
-(void)doThis:(NSInteger)integer{
[API doSomethingWithThisInteger:integer success:^(NSMutableDictionary *data){
...
} failure:^(NSString *error){
integer--;
}
}
I know that I'm supposed to pass in a __block type variable but if I initialized a new one in the function (i.e. __block NSInteger temp = integer) and put temp-- instead of integer-- in the failure block, then self.input would remain the same since the initialization statement copies the value of input instead of referencing to it. What should I do here? Is there a way to make the new variable a reference to the variable I pass into the function? Thanks!
EDIT: solution to problem -
Used a global variable instead of a property -
#implementation
NSInteger input;
....
[self doThis:&input]; //sends in the address of the input
....
- (void)doThis:(NSInteger *)integer{ //takes the pointer of the input instead of its actual value so it gets referenced rather than getting copied
[API doSomethingWithThisInteger:integer success:^(NSMutableDictionary *data){
...
} failure:^(NSString *error){
*integer = *integer - 1; //dereference the pointer to get the value.
}
You have to give a block some reference to variable to modify. By calling doThis: you pass an integer by value (not by reference), so failure block gets effectively just a copy of integer value - so original variable has no chance to get modified.
The same is valid for __block NSInteger temp = integer - temp gets a copy of an integer. Block can modify temp, however it's just a copy of integer - so no chance to change the original value.
To get the value changed, use:
-(void)doThis
{
[API doSomethingWithSuccess:^(NSMutableDictionary *data)
{
...
}
failure:^(NSString *error)
{
self.input--;
}
}
This way you get a reference to input via self. However, it's considered bad in ARC environment because self gets impliciltly captured by the block and this may lead to retain cycle. So, the best way is create weak reference to self and let it get captured by the block:
-(void)doThis
{
__weak typeof(self) weakSelf = self;
[API doSomethingWithSuccess:^(NSMutableDictionary *data)
{
...
}
failure:^(NSString *error)
{
weakSelf.input--;
}
}
P.S. Your question effectively discloses, that you have no idea, how it works - pointers, passing parameters by value/by reference, ObjC blocks etc. You should get more theoretical knowledge about your programming language to avoid such questions in future.
Objective-C, like C, passes everything by value. It welds objects on top of C by putting them on the heap and referring to them by pointer. So what you're passing around isn't the object itself, it's the address of the object. The address itself is passed by value. But if someone knows the address, they can go to the heap and modify the object.
Your input to doThis: is a parameter, integer. So when calling that method what will have happened is:
whatever you wrote where the parameter should be will be evaluated and, if necessary, implicitly cast to `NSInteger';
a copy of that NSInteger will be supplied to the method;
having received its own copy, integer is now equivalent to a local variable for the method.
So e.g. you could do:
[object doThis:8];
The 8 is copied into what is effectively a local variable within doThis:, so you can modify integer all you like regardless of the fact that you passed in a constant.
If you want doThis: to be able to modify the integer then you need to supply a pointer to it. And once you have that you should have no problem using that pointer inside a block. The pointer itself will be captured but, as when passing a pointer into a method, if you modify what the pointer points to then that will effect everybody else that looks there.

iOS: why can't I access a #property from a global Block (outside of method)

I'm trying to create a global block that can be used from any method. I want this block to access #properties of the class. But when I try to do this I get "use of undeclared identifier self" accessing the backing variables _myVar also doesn't work.
Why doesn't this work? And what work around would give me a block that I can access from any method? Thanks.
An example:
#interface myClass()
#property (nonatomic,assign) BOOL subjectSex;
#end
#implementation
// these returns will get: use of undeclared identifier
int (^myBlock) = ^{
if(self.subjectSex) return 1;
return (!_subjectSex);
}
#end
You must define the block inside an instance method. You can then have a static block pointer that all your methods can access. When you assign the block to the pointer you must copy it:
s_blockPtr = [block copy];
Alternatively, you can send the this pointer as argument to the block. It's simpler to understand but may be more typing.
It doesn't so much have to do with property access as that you are using self. (You can use properties of other objects that you have access to without problem.) self does not exist in that scope. self is an implicit parameter in methods. Since your block definition is not inside a method, there is no variable named self (unless you define a global variable named self, but that would probably be a bad idea).
Blocks are nothing it's just a function pointer.If you want to access property in block you have to explicitly set __block in the property i.e.
you have to tell the compiler this is a block type property.
Let's take a closure look on blocks:
suppose there are two threads T1 and T2
//T1 Thread
void fun(int (*funptr)(int a,int b))
{
funptr(2,3);
}
//T2 Thread
int add(int a,int b)
{
return a+b;
}
//Main Thread
fun(&add);
printf("Hello");
From the above code ,assume main thread address is 20004 and executing fun having address 20006 and that fun taking function pointer as an argument which pointing to another function of thread T2 at an address of 20064 which means context switching from Thread T1 and T2, while executing T2 thread,function don't know about the global variables which are in code segment thats why they can't access because they are in different thread and this is the reason blocks are running on different thread.
that's solve.
You can access any object in a block by declaring it block type
#property(nonatomic,retain) __block NSString *strName;
dispatch_async(dispatch_get_current_queue(), ^(void)
{
self.strName= #"XYZ";
});

Should I Release Object in Primitive C-Array

Say you have class Block
Class Block : NSObject
Now, you want to create array in C-style
Block *blocks[5]; // or calling malloc()
Block *aBlock = [[Block alloc] init];
blocks[0] = aBlock;
// at this point, aBlock will be hand over to array blocks slot.
// not like NSArray, object of 'Block' will not retain by #property(retain)
// or should I call retain before hand over the value into its array and release afterward?
// should I still call below code to release object ?
// [aBlock release];
Can someone explain to me should I still need to release the aBlock object afterward?
No because the primitive array won't be retaining each Block object. So if you release it, all Block objects will be cleaned up the moment the function exits scope

Resources