weak definition of a bool in block - objective-c

To define a weak references for objects in block i use something like this
MyViewController *__weak weakSelf= self;
UILabel *__weak weakLabel=ALabel;
///the block code with some examples
up2.completionBlock = ^(NSDictionary *headers, NSString *responseString) {
[weakSelf aMethodInTheController];
[weakLabel setHidden:NO];
};
I have problem with a bool, how i can declare a weak reference to a bool to avoid the warnings "capturing self strongly in this block is likely to lead to a retain cycle" ?
Not works with:
Bool *__weak weakFlag=Aflag;

Well, it's not obvious what you are trying to do here.
There are two possibilities. Perhaps you need to pass a parameter to the block. So there is a variable of type bool or BOOL (they are similar for the purposes of this question) and you want to use it in the block.
Then, good news! You don't need anything at all. Just declare
BOOL some_bool = (YES or NO or some calculation);
and use it later in the block. This works because Boolean types are primitive (they are some kind of integer) and not smart enough to participate in memory management. So the compiler doesn't worry much; it just grabs the value of this variable when the block is created and copies it into the block.
Here's the relevant documentation:
Only the value is captured, unless you specify otherwise. This means that if you change the external value of the variable between the time you define the block and the time it’s invoked, ...
Alternatively, perhaps you want to have a variable which can take logical values and which can be changed by some other object in the time between you create the block and the time when it is run. In that case you need to
wrap boolean into NSNumber
store the strong reference to this NSNumber somewhere in your object
pass it as a weak pointer to the block
E.g.
// somewhere in the interface
#property NSNumber *someImportantFlag
__weak NSNumber *weakFlag = someImportantFlag;
... ^{ ... if(weakFlag.boolValue) ... weakFlag = #(NO); ...}
Thanks to the commenters who made me reread the question and my answer.

Related

Does block parameters need to specify ownership qualifiers when providing weak references?

I'm trying to use blocks in a way where I provide a reference to the object which retains the block, as follows:
typedef void(^RunBlock)(__weak Thing *block_owner, ThingFinishBlock finish);
where Thing has a property run_block, of the type RunBlock.
Thing *thing = [Thing thingWithBlock^(Thing *owner, ThingFinishBlock finish) { ... }];
Calling the run_block from within the Thing goes something like this:
__weak typeof(self) this = self;
_finish_block = ^(){ ... }
self.run_block(this, _finish_block);
So what I'm wondering now is, is it safe to define the run_block's first parameter Thing *owner without prefixing it with __weak, or will this cause a retain loop? I'm unsure, as the pointer is already defined as __weak in the typedef, and the given parameter is already __weak.
^(__weak Thing *owner ...){ ... }
As opposed to
^(Thing *owner, ...) { ... }
Thanks!
No, __weak in parameters is not part of the function type itself.
typedef void(^RunBlock)(__weak Thing *block_owner, ThingFinishBlock finish);
is the same as
typedef void(^RunBlock)(Thing *block_owner, ThingFinishBlock finish);
It's where you implement the block that the __weak in the parameter matters.
Also, I have no idea why you think this has anything to do with retain cycles.

Objective-C block "retain cycle" warning, don't understand why

I've seen several other questions of the same form, but I either a) can't understand the provided answers, or b) don't see how those situations are similar to mine.
I'm writing a Category on UIView to recursively evaluate all the subviews of a UIView and return an Array of subviews passing a test. I've noted where my compiler warning occurs:
-(NSArray*)subviewsPassingTest:(BOOL(^)(UIView *view, BOOL *stop))test {
__block BOOL *stop = NO;
NSArray*(^__block evaluateAndRecurse)(UIView*);
evaluateAndRecurse = ^NSArray*(UIView *view) {
NSMutableArray *myPassedChildren = [[NSMutableArray alloc] init];
for (UIView *subview in [view subviews]) {
BOOL passes = test(subview, stop);
if (passes) [myPassedChildren addObject:subview];
if (stop) return myPassedChildren;
[myPassedChildren addObjectsFromArray:evaluateAndRecurse(subview)];
// ^^^^ Compiler warning here ^^^^^
// "Capturing 'evaluateAndRecurse' strongly in this block
// is likely to lead to a retrain cycle"
}
return myPassedChildren;
};
return evaluateAndRecurse(self);
}
Also, I get a bad_access failure when I don't include the __block modifier in my block's declaration (^__block evaluateAndRecurse). If someone could explain why that is, that would be very helpful too. Thanks!
The problem here is that your block evaluteAndRecurse() captures itself, which means that, if it's ever to be copied (I don't believe it will in your case, but in slightly less-trivial cases it may), then it will retain itself and therefore live forever, as there is nothing to break the retain cycle.
Edit: Ramy Al Zuhouri made a good point, using __unsafe_unretained on the only reference to the block is dangerous. As long as the block remains on the stack, this will work, but if the block needs to be copied (e.g. it needs to escape to a parent scope), then the __unsafe_unretained will cause it to be deallocated. The following paragraph has been updated with the recommended approach:
What you probably want to do here is use a separate variable marked with __unsafe_unretained that also contains the block, and capture that separate variable. This will prevent it from retaining itself. You could use __weak, but since you know that the block must be alive if it's being called, there's no need to bother with the (very slight) overhead of a weak reference. This will make your code look like
NSArray*(^__block __unsafe_unretained capturedEvaluteAndRecurse)(UIView*);
NSArray*(^evaluateAndRecurse)(UIView*) = ^NSArray*(UIView *view) {
...
[myPassedChildren addObjectsFromArray:capturedEvaluateAndRecurse(subview)];
};
capturedEvaluateAndRecurse = evaluteAndRecurse;
Alternatively, you could capture a pointer to the block, which will have the same effect but allow you to grab the pointer before the block instantiation instead of after. This is a personal preference. It also allows you to omit the __block:
NSArray*(^evaluateAndRecurse)(UIView*);
NSArray*(^*evaluteAndRecursePtr)(UIView*) = &evaluateAndRecurse;
evaluateAndRecurse = ^NSArray*(UIView*) {
...
[myPassedChildren addObjectsFromArray:(*evaluateAndRecursePtr)(subview)];
};
As for needing the __block, that's a separate issue. If you don't have __block, then the block instance will actually capture the previous value of the variable. Remember, when a block is created, any captured variables that aren't marked with __block are actually stored as a const copy of their state at the point where the block is instantiated. And since the block is created before it's assigned to the variable, that means it's capturing the state of the capturedEvaluteAndRecurse variable before the assignment, which is going to be nil (under ARC; otherwise, it would be garbage memory).
In essence, you can think of a given block instance as actually being an instance of a hidden class that has an ivar for each captured variable. So with your code, the compiler would basically treat it as something like:
// Note: this isn't an accurate portrayal of what actually happens
PrivateBlockSubclass *block = ^NSArray*(UIView *view){ ... };
block->stop = stop;
block->evaluteAndRecurse = evaluateAndRecurse;
evaluteAndRecurse = block;
Hopefully this makes it clear why it captures the previous value of evaluateAndRecurse instead of the current value.
I've done something similar, but in a different way to cut down on time allocating new arrays, and haven't had any problems. You could try adapting your method to look something like this:
- (void)addSubviewsOfKindOfClass:(id)classObject toArray:(NSMutableArray *)array {
if ([self isKindOfClass:classObject]) {
[array addObject:self];
}
NSArray *subviews = [self subviews];
for (NSView *view in subviews) {
[view addSubviewsOfKindOfClass:classObject toArray:array];
}
}

Correct way of setting a BOOL property

I have a BOOL property that I want to set in my class initializer.
#property (assign, nonatomic) BOOL isEditMode;
- (id)init
{
. . .
[self setValue:NO forKey:isEditMode];
return self;
}
The compiler gives me an "Incompatible integer to pointer conversion" warning. What am i doing wrong here?
The Key-Value Coding method setValue:forKey: only accepts objects as arguments. To set a BOOL, you need to wrap the number in a value object with [NSNumber numberWithBool:NO]. But there's little reason to do that. Key-Value Coding is a roundabout way to accomplish this. Either do self.isEditMode = NO or just isEditMode = NO. The latter is preferable in an init method (because setters can run arbitrary code that might not be desirable before an object is fully set up).
But to elaborate on the first point: The reason Key-Value Coding works this way is because the type system can't represent an argument that's sometimes an object and at other times a primitive value. So KVC always deals with objects and just autoboxes primitive values as necessary. Similarly, if you do [yourObject valueForKey:#"isEditMode"], you'll get back an NSNumber object wrapping the real value.
The correct syntax to set a property is just
self.isEditMode = NO;
If you want to use -setValue:forKey: you'd have to write it as
[self setValue:[NSNumber numberWithBOOL:NO] forKey:#"isEditMode"];
However, there's absolutely no reason to do this in your situation.
That said, since you're in an init method, I would strongly recommend avoiding any property access whatsoever and instead using the ivar directly, as in
isEditMode = NO;
This avoids the possibility of an overridden setter being called (either in this class or a subclass) that makes the assumption that the object has already completed initialization. For this same reason you also want to avoid property access inside of -dealloc.
You can just assign the value directly:
isEditMode = NO;
I think you mean:
self.isEditMode = NO;
If your code does indeed compile (I'm pretty new to Objective-C so I don't know) setValue probably takes a pointer to a string (#"isEditMode", e.g.) and not some other type (isEditMode, e.g.).

What does the "__block" keyword mean?

What exactly does the __block keyword in Objective-C mean? I know it allows you to modify variables within blocks, but I'd like to know...
What exactly does it tell the compiler?
Does it do anything else?
If that's all it does then why is it needed in the first place?
Is it in the docs anywhere? (I can't find it).
It tells the compiler that any variable marked by it must be treated in a special way when it is used inside a block. Normally, variables and their contents that are also used in blocks are copied, thus any modification done to these variables don't show outside the block. When they are marked with __block, the modifications done inside the block are also visible outside of it.
For an example and more info, see The __block Storage Type in Apple's Blocks Programming Topics.
The important example is this one:
extern NSInteger CounterGlobal;
static NSInteger CounterStatic;
{
NSInteger localCounter = 42;
__block char localCharacter;
void (^aBlock)(void) = ^(void) {
++CounterGlobal;
++CounterStatic;
CounterGlobal = localCounter; // localCounter fixed at block creation
localCharacter = 'a'; // sets localCharacter in enclosing scope
};
++localCounter; // unseen by the block
localCharacter = 'b';
aBlock(); // execute the block
// localCharacter now 'a'
}
In this example, both localCounter and localCharacter are modified before the block is called. However, inside the block, only the modification to localCharacter would be visible, thanks to the __block keyword. Conversely, the block can modify localCharacter and this modification is visible outside of the block.
#bbum covers blocks in depth in a blog post and touches on the __block storage type.
__block is a distinct storage type
Just like static, auto, and volatile, __block is a storage type. It
tells the compiler that the variable’s storage is to be managed
differently....
However, for __block variables, the block does not retain. It is up to you to retain and release, as needed.
...
As for use cases you will find __block is sometimes used to avoid retain cycles since it does not retain the argument. A common example is using self.
//Now using myself inside a block will not
//retain the value therefore breaking a
//possible retain cycle.
__block id myself = self;
When you don't use __block, the block copies the variable (call-by-value), so even if you modify the variable elsewhere, the block doesn't see the changes.
__block makes the blocks keep a reference to the variable (call-by-reference).
NSString* str = #"hello";
void (^theBlock)() = ^void() {
NSLog(#"%#", str);
};
str = #"how are you";
theBlock(); //prints #"hello"
In these 2 cases you need __block:
If you want to modify the variable inside the block and expect it to be visible outside:
__block NSString* str = #"hello";
void (^theBlock)() = ^void() {
str = #"how are you";
};
theBlock();
NSLog(#"%#", str); //prints "how are you"
If you want to modify the variable after you have declared the block and you expect the block to see the change:
__block NSString* str = #"hello";
void (^theBlock)() = ^void() {
NSLog(#"%#", str);
};
str = #"how are you";
theBlock(); //prints "how are you"
__block is a storage qualifier that can be used in two ways:
Marks that a variable lives in a storage that is shared between the lexical scope of the original variable and any blocks declared within that scope. And clang will generate a struct to represent this variable, and use this struct by reference(not by value).
In MRC, __block can be used to avoid retain object variables a block captures. Careful that this doesn't work for ARC. In ARC, you should use __weak instead.
You can refer to apple doc for detailed information.
__block is a storage type that is use to make in scope variables mutable, more frankly if you declare a variable with this specifier, its reference will be passed to blocks not a read-only copy for more details see Blocks Programming in iOS
hope this will help you
let suppose we have a code like:
{
int stackVariable = 1;
blockName = ^()
{
stackVariable++;
}
}
it will give an error like "variable is not assignable" because the stack variable inside the block are by default immutable.
adding __block(storage modifier) ahead of it declaration make it mutable inside the block i.e __block int stackVariable=1;
From the Block Language Spec:
In addition to the new Block type we also introduce a new storage qualifier, __block, for local variables. [testme: a __block declaration within a block literal] The __block storage qualifier is mutually exclusive to the existing local storage qualifiers auto, register, and static.[testme] Variables qualified by __block act as if they were in allocated storage and this storage is automatically recovered after last use of said variable. An implementation may choose an optimization where the storage is initially automatic and only "moved" to allocated (heap) storage upon a Block_copy of a referencing Block. Such variables may be mutated as normal variables are.
In the case where a __block variable is a Block one must assume that the __block variable resides in allocated storage and as such is assumed to reference a Block that is also in allocated storage (that it is the result of a Block_copy operation). Despite this there is no provision to do a Block_copy or a Block_release if an implementation provides initial automatic storage for Blocks. This is due to the inherent race condition of potentially several threads trying to update the shared variable and the need for synchronization around disposing of older values and copying new ones. Such synchronization is beyond the scope of this language specification.
For details on what a __block variable should compile to, see the Block Implementation Spec, section 2.3.
It means that the variable it is a prefix to is available to be used within a block.

Why shouldn't I use the getter to release a property in objective-c?

I was told by a fellow StackOverflow user that I should not use the getter method when releasing a property:
#property(nonatmic, retain) Type* variable;
#synthesize variable;
// wrong
[self.variable release];
// right
[variable release];
He did not explain in detail why. They appear the same to me. My iOS book said the getter on a property will look like this:
- (id)variable {
return variable;
}
So doesn't this mean [self variable], self.variable, and variable are all the same?
For a retained property with no custom accessor, you can release the object by:
self.variable = nil;
This has the effect of setting the ivar (which may not be called 'variable' if you have only declared properties) to nil and releasing the previous value.
As others have pointed out, either directly releasing the ivar (if available) or using the method above is OK - what you must not do is call release on the variable returned from a getter.
You can optionally write custom getter behavior, which may result in completely different behavior. So, you cannot always assume that [variable release] has the same results as [self.variable release].
As well, you can write custom properties without an exclusive ivar backing them... it can get messy fast if you start releasing objects from references returned by getters!
There may be additional reasons that I'm unaware of...
A typical getter will look more like this:
- (id)variable {
return [[variable retain] autorelease];
}
So if you use [self.variable release] you have an additional retain and autorelease that you don't really need when you just want to release the object and that cause the object to be released later than necessary (when the autorelease pool is drained).
Typically, you would either use self.variable = nil which has the benefit that it also sets the variable to nil (avoiding crashes due to dangling pointers), or [variable release] which is the fastest and may be more appropriate in a dealloc method if your setter has custom logic.
not all getters take this form:
- (id)variable { return variable; }
...that is merely the most primitive form. properties alone should suggest more combinations, which alter the implementation. the primitive accessor above does not account for idioms used in conjunction with memory management, atomicity, or copy semantics. the implementation is also fragile in subclass overrides.
some really brief examples follow; things obviously become more complex in real programs where implementations become considerably more complex.
1) the getter may not return the instance variable. one of several possibilities:
- (NSObject *)a { return [[a copy] autorelease]; }
2) the setter may not retain the instance variable. one of several possibilities:
- (void)setA:(NSObject *)arg
{
...
a = [arg copy];
...
}
3) you end up with memory management implementation throughout your program, which makes it difficult to maintain. the semantics of the class (and how it handles instance variables' ref counting) should be kept to the class, and follow conventions for expected results:
- (void)stuff:(NSString *)arg
{
const bool TheRightWay = false;
if (TheRightWay) {
NSMutableString * string = [arg mutableCopy];
[string appendString:#"2"];
self.a = string;
[string release];
// - or -
NSMutableString * string = [[arg mutableCopy] autorelase];
[string appendString:#"2"];
self.a = string;
}
else {
NSMutableString * string = [arg mutableCopy];
[string appendString:#"2"];
self.a = string;
[self.a release];
}
}
failing to follow these simple rules makes your code hard to maintain and debug and painful to extend.
so the short of it is that you want to make your program easy to maintain. calling release directly on a property requires you to know a lot of context of the inner workings of the class; that's obviously bad and misses strong ideals of good OOD.
it also expects the authors/subclassers/clients to know exactly how the class deviates from convention, which is silly and time consuming when issues arise and you have to relearn all the inner details when issues arise (they will at some point).
those are some trivial examples of how calling release on the result of a property introduces problems. many real world problems are much subtler and difficult to locate.