Correct way of setting a BOOL property - objective-c

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.).

Related

weak definition of a bool in block

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.

Objective-C: Is there any trick to avoid casting of NSArray objects?

Very often I find myself casting objects in NSArray to my types, when I want to access their specific properties with dot notation (instead of getter) without creating an extra variable.
Is there any cool feature or trick to tell objective-c which one class of objects I'm going to store to NSArray, so that compiler will assume objects in an array to be my type, not an id?
If you mean you're doing things like:
x = ((MyClass *)[myArray objectAtIndex:2]).property1;
You can just split it into two lines to be easier to read:
MyClass *myObject = [myArray objectAtIndex:2]
x = myObject.property1;
If you're really set on the first case, you could make a category on NSArray that has an accessor for your type:
#implementation NSArray (MyCategory)
- (MyClass *)myClassObjectAtIndex:(NSUInteger)index
{
return [self objectAtIndex:index];
}
#end
And then you can use it like you want:
x = [myArray myClassObjectAtIndex:2].property1;
Don't use properties in this situation. You can't say
arr[ix].myProperty
But you can always say
[arr[ix] myProperty]
Strictly answering to your question, no.
There's no language support for indicating the parametric type of a collection, i.e. something like NSArray<MyClass>.
That said, you can find workarounds for avoiding an explicit cast.
Since the returned object is of type id you can invoke any - existing - method on it and the compiler won't raise an eyebrow, unless you're using dot-syntax notation, which has stricter compiler checks.
So for instance
NSString * name = [people[0] firstName];
works flawlessly without a cast, whereas
NSString * name = people[0].firstName;
doesn't.

dot syntax vs method syntax with getter=

I'm not sure how much use this question is but it seems interesting to me...
I thought that using property/synthesize statements was equivalent to me creating the getter/setter. Therefore
// .h
#property (nonatomic) BOOL on;
// .m
#synthesize on = _on;
// In my mind synthesizes the following methods
// - (BOOL)on;
// - (void)setOn:(BOOL)on;
However if I change the declarations to the following:
v
#property (nonatomic, getter=isOn) BOOL on;
#synthesize on = _on;
// In my mind synthesizes the following
// - (BOOL)isOn;
// - (void)setOn:(BOOL)on;
Then given the above I override the getter so I know when it is called:
- (BOOL)isOn;
{
NSLog(#"I was called");
return _on;
}
Now calling the following on an instance (myClass) results in:
NSLog(#"%d", [myClass isOn]);
//=> 2012-02-09 22:18:04.818 Untitled[1569:707] I was called
//=> 2012-02-09 22:18:04.820 Untitled[1569:707] 1
NSLog(#"%d", myClass.isOn);
//=> 2012-02-09 22:18:24.859 Untitled[1599:707] I was called
//=> 2012-02-09 22:18:24.861 Untitled[1599:707] 1
NSLog(#"%d", myClass.on); // This is the one I didn't expect to work
//=> 2012-02-09 22:18:55.568 Untitled[1629:707] I was called
//=> 2012-02-09 22:18:55.570 Untitled[1629:707] 1
I had always assumed that if I was using a property in this sense it was perfectly valid to use the getter/setter with dot syntax in the form
myClass.isOn;
myClass.on = on;
From another question it was suggested that when using dot syntax I should use the property name like this:
myClass.on // Correct
myClass.isOn // Incorrect
Although this works it seem slightly less logical because I know there is no underlying method - (BOOL)on it is instead mapped to - (BOOL)isOn
My questions are (using the latter example)
Is this a bug or should myClass.on really be silently changed to call - (BOOL)isOn
Semantically speaking I am accessing state not invoking behaviour so is my current use of dot syntax correct? (e.g. myClass.isOn)
Update
Although no one has explicitly said it I have reasoned that using .isOn is bad form because regardless of the fact that under the hood the same method is called, semantically isOn is asking a question, which is more behaviour rather than state.
However I am still unclear on where the "magic" wiring goes on that turns calls to myClass.on into [myClass isOn]
Update 2
After looking around the docs some more I found this section on Declared Properties. Using the following code I can inspect a class' properties:
id MyClass = objc_getClass("MyClass");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(MyClass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSLog(#"Name: %s, attributes: %s\n", property_getName(property), property_getAttributes(property));
}
//=> 2012-02-10 07:10:28.333 Untitled[934:707] Name: on, attributes: Tc,GisOn,V_on
So we have the following attributes:
name = on
type = char (Tc)
getter = isOn (GisOn)
variable = _on (V_on)
With all of this information available at runtime it kind of leaves the question is this lookup done at runtime or compile time like some answers suggest?
However I am still unclear on where the "magic" wiring goes on that turns calls to myClass.on into [myClass isOn]
The logic surely goes as follows, when compiling an obj.name in a getting context:
if(there is an accessible #property for name in scope)
{
if(there is a custom getter specified)
compile "[obj customGetter]"
else
compile "[obj name]"
}
else if (there is an an accessible instance method name in scope)
compile "[obj name]"
else
{
compile "[obj name]"
warn obj may not respond to name
}
There are other ways a language/execution environment can handle custom getter names, but given that Obj-C puts the declaration in the header (which is public) the above is a good guess as to where the custom getter logic is performed - when compiling the call site.
From your experiment we can infer that dot syntax is interpreted as follows:
is there a property with this name? If so, does it have a specified getter / setter name? if so, let's call that method.
otherwise, make up an appropriate method name (direct if we're getting, setXX if we're setting) and throw that at the receiver.
You can, for example, try to use .count against an NSArray instance. Before the abomination police kick in your doors, you may have time to see that it works.
To actually answer your question, in my mind dot notation should only be used to access properties, and in that case you should use the property name as declared in the interface. So .on for a UISwitch. I don't know why the getter name isn't given in the synthesize statement instead of the property declaration, it seems to belong in implementation rather than interface to me.
Well concerning dot notation, let me cite Aaron Hillegass (Cocoa Programming for Mac OSX, 3rd. Ed):
"Overall, I think that this is a rather silly addition to the language since we already had a syntax for sending messages."
When you have a member variable on, and your getter for this variable is called isOn then .on and .isOn are two very different kind of things. By using the getter (and probably a setter, too) you will adhere to the "information hiding" promise, whereas by using direct access to the member variables you won't. Cocoa won't enforce those things as it is relying on conventions. It's up to you to decide which way is right for you. Considering convention, you would have to stick to setters and getters - no matter what names you give them, though.
Property declarations are merely shorthand for regular method declarations. E.g.:
#property int color;
#property (getter=isOn) BOOL on;
becomes these method declarations:
- (int)color;
- (void)setColor:(int)value;
- (BOOL)isOn;
- (void)setOn:(BOOL)on;
You can call these methods just like any other method:
[foo color];
[foo isOn];
Likewise, dot notation is merely informal shorthand for calling plain old methods. For example:
x = #"Hello".length;
x = foo.on;
x = foo.isOn;
becomes
x = [#"Hello" length];
x = [foo isOn];
x = [foo isOn];
Note that #"Hello".length works even though NSString does not actually declare a property named "length". By default, foo.bar always expands to [foo bar] unless bar has been declared a property with a custom getter. If bar happens to be the name of a valid method then it will work without error.
Likewise, in your example foo.isOn works even though you don't actually declare a property named "isOn". Rather "isOn" is the name of a method that just happens to be the getter method for your "on" property.
So, while foo.isOn may work, it's considered bad form because isOn is not actually the name of the property.
What you cannot do is this:
x = [foo on]; // Error
because you never declare an on method.

Help me understand why: [self propertyName] works while propertyName doesn't

So I had a class defined with a property - we'll call it propertyName for the sake of this example. I had the property setup with #synthesize in my implementation.
I have a method called objectToNSDictionary which basically dumps that property into a dictionary:
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:
[self propertyName], #"propertyName", nil];
I return that dict to the caller I use a JSonWriter to convert it to a string and pass it off to some service...
Suffice it to say that the above works. However, my original implementation didn't use [self propertyName] but instead just used propertyName. When I did that, I always had an error saying unrecognized selector sent to instance when I tried to use the object in the caller.
What's the difference in syntax really saying and why does one work and not the other?
When you use [self propertyName] you are referencing the property you defined for your class, via the synthesized getter method. When you use propertyName directly you are bypassing the property and using the class ivar directly. This will work as long as your ivar really is called propertyName, which is not required and might not be the case. Generally its a bad idea to access your ivar directly because doing so circumvents the memory management scaffolding that the compiler generates for you.
You need to post relevant code from your calling class to be able to tell why you are getting a 'selector not recognized' message.

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.