Questions about a readonly #property in ARC - objective-c

In my interface (.h) file, I have
#property(readonly) NSString *foo;
and in my implementation (.m) file, I have
#synthesize foo;
With ARC turned on, the compiler gives me this error: Automatic Reference Counting Issue: ARC forbids synthesizing a property of an Objective-C object with unspecified ownership or storage attribute.
The error goes away if I add a strong, weak, or copy to the property. Why is this? Why would there be any differences between these things for a read-only property, what are those differences, and why does the programmer have to worry about them? Why can’t the compiler intelligently deduce a default setting for a read-only property?
Another question while I’m at it: strong, weak, or copy are the only things that make sense in ARC, right? I shouldn’t be using retain and assign anymore, should I?

You've declared a #property that doesn't have a backing ivar. Thus, when the compiler sees #synthesize, it tries to synthesize a backing ivar for you. But you haven't specified what kind of ivar you want. Should it be __strong? __weak? __unsafe_unretained? Originally, the default storage attribute for properties was assign, which is the same as __unsafe_unretained. Under ARC, though, that's almost always the wrong choice. So rather than synthesizing an unsafe ivar, they require you to specify what kind of ivar you want.

With the latest version of Xcode and recent clang compilers, this error no longer occurs. You can specify a property as #property(nonatomic, readonly) NSObject *myProperty; in the interface, synthesize it in the implementation, and the resulting ivar is assumed to be strong. If you want to be explicit or choose weak, you can do so in the original property, like #property(nonatomic, readonly, retain). Objective-C is incrementally becoming less redundant.

It is here as a declaration to the rest of your code.
When you a access the property of this class from an other part of your code, you need to know if the object you get is strong or weak.
It used to be more obvious when ARC didn't exists, because the programmer needed this information. Now, ARC makes a lot of things transparent, so it is true, you might wonder why it is still here.
Why can’t the compiler intelligently deduce a default setting for a read-only property?
I assume it would be pretty easy to set the convention that no keyword means strong or means weak. If it hasn't been done, they surely had a reason.

Related

Modern Objective-C (2013) and declaring ivars/using #property, #dynamic, and #synthesize

With the current version of Objective-C, what are the official standards and best practices for declaring ivars, using #property and #synthesize? There are a lot of posts and resources on the topic but most of them are fairly antiquated from a year or two ago. I recently learned to only declare ivars in a statement block in the implementation of a class so that the encapsulation principles of OOP aren't broken but is declaring ivars even necessary in this day and age? What would be a possible use case where doing:
#interface MyClass()
#property (nonatomic) NSString* data;
#end
#implementation MyClass{
#private
NSString* _data;
}
#end
is necessary? To further that, is it ever necessary to use #synthesize? My understanding is that using #property will auto-synthesize both the accessor methods as well as the backing ivars. I've done some experimentation and I noticed that when I don't declare NSString* _data', I can still access_data' in my class implementation. Does that mean that declaring ivars come down to a matter of style, up to the discretion of the programmer? Could I condense my code and remove all ivar declarations in the statement blocks in my implementation and just use #property in my private interface? If that's not the case, what are the advantages and disadvantages of explicitly declaring ivars?
Finally, #dynamic. From what I can gather, it's used to say to the compiler, "Hey compiler, don't auto-generate the accessor method and don't worry if you don't find an implementation for it, I'll provide one at runtime". Is that all #dynamic is used for or is there more to it?
I just want to clarify all these things because it seems like there's a lot of different opinions and that there's not necessarily one right answer. Plus as Objective-C grows and progresses, those answers will change so it'll be nice to have a concise and up-to-date guide. Thanks everyone!
(Also if there's anything that I could word better or make clearer, let me know)
EDIT:
In summary, what I'm asking is this:
1) Is declaring ivars with modern Objective-C necessary?
2) Can I achieve the same effects of declaring ivars and corresponding properties by just using #property?
3) What is #dynamic used for?
4) Can I completely forgo the use of #synthesize or is there a good use case for it?
Upvote and down vote as you see fit.
There's a lot to answer here. I'll break it down:
Declaring ivars
As you've correctly noted, modern versions of the compiler will synthesize backing instance variables for declared #properties. The exception to this is on 32-bit Macs, where the modern Objective-C runtime, including non-fragile instance variables, is not available. Assuming your application is not targeting 32-bit OS X, you don't need to explicitly declare the backing ivar for an #property.
If you still want to use an ivar directly, without a corresponding #property (something I consider a bad idea most of the time), you of course must still explicitly declare the ivar.
#dynamic
#dynamic is as you've said meant to tell the compiler "don't synthesize accessors for this property, I'll do it myself at runtime". It's not used all that often. One place it is used is in NSManagedObject subclasses, where if you declare a modeled property in the header, you don't want to compiler to complain that there's no implementation of accessors for that property, nor do you want it to generate accessors itself. NSManagedObject generates accessors for modeled properties at runtime. The story is similar for custom CALayer subclasses.
#synthesize
#synthesize explicitly tells the compiler to synthesize accessor methods, and (on iOS and 64-bit Mac) a corresponding ivar for the specified property. There are three main cases where you still need to use it:
32-bit Mac apps.
If you've written your own custom setter and getter (or just getter for readonly properties). In this case, the compiler won't synthesize accessors because it sees yours. However, it also won't synthesize the backing ivar. So, you must use #synthesize someProperty = _someProperty;, to tell the compiler to synthesize an ivar. It still won't synthesize accessor methods of course. Alternatively, you can explicitly declare a backing ivar. I favor using #synthesize in this case.
If you want to use a different name for the property's backing ivar than the default (property name with an added underscore prefix). This is rare. The main case I can think of for using it is when transitioning existing, older code, that includes direct ivar access and where the ivars are not underscore-prefixed.
Best current practice seems to be to use properties for all ivars placing the property either in the .h file if they are to be exposed and in the .m file in a class extension if local to the class.
No #synthesize is needed unless the ivar needs to be different than the underscore prepended property name.
Yes, #dynamic is as you describe.
Further, it is no longer necessary to declare local instance methods or order such that the method is above the use.
First off, #synthesize is gone for these scenarios: do not have to do it any more.
Secondly, you don't need the private ivar anymore either.
So in essence, you can just do properties.
The way of controlling access is the same idiom that had become popular before MOC dropped: put the property in the public interface as readonly and then make a readwrite version in the private interface (which should be, as you show above, merely the name with open and close parens).
Note also, that many of the things that cluttered up the public interface in the past can now ONLY be in the private interface, so for instance IBOutlets, etc., since the controller is going to be the only thing diddling them.
I never see #dynamic used anywhere except in CoreDate-generated entities.
For someone who first worked with C++ where the dream was always that the header/interface merely show the user of the class what they needed and all other details would be hidden, I think MOC (Modern Objective C) is a dream come true.
BTW, highly recommend the intro session from WWDC Modern Objective C (from 2012) and the one this year was great too.

In Objective-C with ARC, is it true that we usually only need to specify nonatomic as property attributes?

It is strange that in Big Nerd Ranch iOS 5 book (p.73) and Programming iOS 5 book (O'Reilly, p.314) (updadte: even Kochan's Objective-C book Fourth edition), in the context of ARC, they say the default for properties attribute is assign... But Apple's documentation says the default is strong.
I also tried a simple program where if I don't specify strong, the program works ok, and if I specify strong, it works the same, and when assign is used instead, the compiler shows a warning, so it seems the default is indeed strong.
So if most of the time, we want
#property (nonatomic, readwrite, strong) NSMutableArray *foo;
then we can just write
#property (nonatomic) NSMutableArray *foo;
as the other two (readwrite and strong) are the default?
readwrite and strong, are indeed the default under ARC*. Under manual reference counting, assign was (is) the default. I prefer to explicitly specify these, because it makes it clearer what the #property's parameters are instead of relying on the person reading the code knowing what the defaults are.
*strong is the default assuming you've either let the compiler synthesize an instance variable for you, or have declared an instance variable without an explicit ownership qualifier (in which case the ivar is __strong by default anyway). Otherwise, the default property ownership type matches the ownership qualifier in the ivar's declaration. So, if you explicitly declare an ivar with __weak, then declare an #property for it without an ownership qualifier, the synthesized property will be weak. This is all documented in the Clang ARC documentation.
By default, an object property is strong, atomic, readwrite. See
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html

What is the correct way to declare a readonly property for ios using ARC

I am new to iOS development in general and have never dealt with manual reference counting (retain, release, autorelease). As such I don't have a good understanding of what magic ARC is performing.
I thought I understood until I was asked what type of ownership (weak, strong, assign, etc) should be given to a readonly property pointing at an object, such as:
#property (readonly,nonatomic) NSString* name;
I read here
Questions about a readonly #property in ARC that leaving off the strong/weak won't actually compile unless you specify a backing variable when you #synthesize the property; I just so happened to be specifying a backing ivar like this:
#synthesize name = _name;
Now I understand that the default 'lifetime qualifier' of a variable is strong, from here: http://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW4
So to cut a long story short - I am indirectly defining my property as (readonly,nonatomic,strong) as the _name ivar is implicitly declared as __strong.
I have a few questions:
Is strong the correct lifetime qualifier to use? I assume that it is, otherwise the object backing my NSString* wouldn't be owned anywhere and would thus be freed automatically (coming from Java land this makes sense as all references are strong by default).
Are there any other modifiers which make sense in this situation, such as copy or assign?
Does declaring the property as (readonly,nonatomic,strong) and (readonly,nonatomic) make any difference to the code which consumes the property? eg. does declaring it without the strong keyword cause the object pointer to be stored as __unsafe_unretained where the strong property would be stored in a __strong pointer?
Thanks!
EDIT
So as I understand now, the following applies to readonly properties:
For non-NSObject* types (int, float, void*, etc) use (readonly, assign).
For object pointers, use (readonly, strong) or (readonly, copy) - these function the same for readonly properties but you may want the copy semantics if you extend/subclass and redeclare the property as readwrite.
For object pointers, (readonly, weak) only makes sense if you are going to be storing an already weak pointer in that property (that pointer must be strong elsewhere or the object will be deallocated).
strong is correct to use if you want to keep a strong (owning) reference to whatever it is that you are pointing to. Usually, you do want strong, but in order to prevent circular references (particularly in parent/child relationships where if the parent points to the child and the child points to the parent, they will never be released) you sometimes need to use weak references. Also, if you want to keep a pointer to an object that you don't own but want it to be valid only as long as it exists, then you want to use a weak pointer because when it gets deallocated by the owner, your pointer will automatically get set to nil and won't be pointing to memory that it shouldn't be.
assign is used with scalar values, and is the default setter. copy makes sense if you want to automatically make a copy of the object and set your pointer to the copy instead of pointing to the original object. It only makes sense to do this if you have a specific need (usually because you don't want the object to mutate on you).
The link that you provided which shows that __strong is the default (and therefore you don't need to specify it) refers to variables and not to declared properties. The default for declared properties is assign so it certainly will make a difference. If you were wanting assign however, it makes no difference whether you specify it or not (other than just to be clear that it is what you wanted).
EDIT: However, as Jacques pointed out, this is changing with LLVM 3.1 and the default is changing from assign to strong. In this case, it makes absolutely no difference whether or not you specify strong and can leave it out if you want. Personally I think that it is good to spell it out (especially since there is a conflict between different versions) so that everyone looking at the code is on the same page. Others may disagree on this point though. :)
I would suggest reading the Declared Properties section of The Objective-C Programming Language here: <document removed by Apple with no direct replacement>.
One additional point: properties can get redeclared from readonly to readwrite. For example, a subclass may make a read-only property from the superclass read-write, similar to how many Cocoa classes have subclasses that add mutability. Likewise, a property may be publicly read-only but the class may redeclare it read-write for internal use in a class extension. So, when the class sets its own property it can take advantage of a synthesized setter that does memory management properly and emits appropriate Key-Value Observing change notifications.
As things currently stand, all of the other attributes of the property have to be consistent. It's conceivable that the compiler could relax this requirement. (Some consider it a bug.) Anyway, that's one reason to declare a readonly property with an ownership attribute like strong, copy, or weak – so that it will match the readwrite redeclaration elsewhere.
With regard to your question 3, are you asking if the ownership qualifier affects code which calls the getter? No, it doesn't.
These 2 lines of code work for me:
.h file:
#property (nonatomic, readonly, copy) NSString *username;
.m file:
#property (nonatomic, readwrite, copy) NSString *username;

Change with properties and ivars after ARC migration

I have used the "Convert to Objective C ARC" option in Xcode 4.3 to convert a project started in Xcode 4.0 to use ARC. After fixing errors that the tool found, I went trough the process where the migration tool has removed all the release messages as well as retain attributes in my properties declarations. So now I have all of my properties having only (nonatomic) attribute. From reading the documentation I still don't have a clear answer on what to do.
So my question is: In case you omit the keyword regarding the setter semantics (strong, weak, retain, assign) in the property declaration, what is the default attribute on properties when using ARC?
I found in the documentation that the default property attribute is assign. However, they also say that now the default attribute for ivars, in case you omit it, is strong.
To better explain my question, here is an example. I header file we have the declaration:
#property (nonatomic) MyClass *objectToUse;
and in our implementation we just have
#synthesize objectToUse;
If we then write inside some method:
self.objectToUse = [[MyClass alloc] init];
have we created an strong (retain) or weak (assign) reference? If we instead write
objectToUse = [[MyClass alloc] init];
by using the ivar have we changed the situation regarding the object retention policy? It seems to me that now with ARC, the best practice of using the properties for memory management is not the same practice anymore.
I've opened an Technical Support Incident. The engineer verified that the default was changed from "assign" to "strong". The reason is exactly the inconsistency you described. Now ivars and #properties have the same default.
He said both the documentation (and warnings some people are getting) are wrong and will be fixed. (The conversion tool is correct.) Until that is done, I would avoid the implicit default altogether. Always explicitly specify "strong", "weak", or "assign".
Edit: The clang documentation now officially documents this change.
The default relationship type is still assign, i.e. a weak ref. In addition, in ARC mode the compiler will generate an error when #synthesizeing accessors unless you explicitly specify a relationship type.
The difference between assigning to self.objectToUse and objectToUse is that the second form will always use ARC to retain or assign, while the first form will use copy if you specified a copy relationship.

Using instance variables with Modern Runtime

I have several years of experience in Obj-c and Cocoa, but am just now getting back into it and the advances of Obj-C 2.0 etc.
I'm trying to get my head around the modern runtime and declaring properties, etc. One thing that confuses me a bit is the ability in the modern runtime to have the iVars created implicitly. And of course this implies that in your code you should always be using self.property to access the value.
However, in init* and dealloc(assuming you're not using GC) methods we should be using the iVar directly (in the current runtime).
So questions are:
Should we use property accessors in init* and dealloc with Modern Runtime?
If so, why is this different? Is it just because the compiler can't see the iVar?
If I need to override an accessor, can I still access that iVar that will be defined at runtime or do I have to define an actual iVar that the runtime will then use?
Again, if I can access the synthesized iVar, why can't I continue to do this for the init* and dealloc methods?
I read the docs several times, but they seemed a bit vague about all of this and I want to be sure that I understand it well in order to decide how I want to continue coding.
Hope that my questions are clear.
Quick summary of testing:
If you don't declare the ivar in legacy, compiler is completely unhappy
If you use #ifndef __OBJC2__ around ivar in legacy compiler is happy and you can use both ivar directly and as property
In modern runtime, you can leave the ivar undefined and access as property
In modern runtime, trying to access ivar directly without declaration gives error during compile
#private declaration of ivar, of course, allows direct access to ivar, in both legacy and modern
Doesn't really give a clean way to go forward right now does it?
In the current (OS X 10.5/GCC 4.0.1) compiler, you cannot directly access the runtime-synthesized ivars. Greg Parker, one of the OS X runtime engineers put it this way on the cocoa-dev list (March 12, 2009):
You can't in the current compiler. A
future compiler should fix that. Use
explicit #private ivars in the
meantime. An #private ivar should not
be considered part of the contract -
that's what #private means, enforced
by compiler warnings and linker
errors.
And why isn't there a way to
explicitly declare instance variables
in the .m file for the new runtime?
Three reasons: (1) there are some
non-trivial design details to work
out, (2) compiler-engineer-hours are
limited, and (3) #private ivars are
generally good enough.
So, for now you must use dot-notation to access properties, even in init and dealloc. This goes against the best practice of using ivars directly in these cases, but there's no way around it. I find that the ease of using runtime-synthesized ivars (and the performance benefits) outweigh this in most cases. Where you do need to access the ivar directly, you can use a #private ivar as Greg Parker suggests (there's nothing that prevents you from mixing explicitly declared and runtime-synthesized ivars).
Update With OS X 10.6, the 64-bit runtime does allow direct access to the synthesized ivars via self->ivar.
Since instance variables themselves can only be synthesized in the modern runtime (and must be declared in the #interface under 32-bit or pre-Leopard), it's safest / most portable to also declare the ivar
Should we use property accessors in init* and dealloc with Modern Runtime?
My rule of thumb is "possibly" for -init*, and "usually not" for -dealloc.
When initializing an object, you want to make sure to properly copy/retain values for ivars. Unless the property's setter has some side effect that makes it inappropriate for initialization, definitely reuse the abstraction the property provides.
When deallocating an object, you want to release any ivar objects, but not store new ones. An easy way to do this is to set the property to nil (myObject.myIvar = nil), which basically calls [myObject setMyIvar:nil]. Since messages to nil are ignored, there is no danger in this. However, it's overkill when [myIvar release]; is usually all you need. In general, don't use the property (or directly, the setter) in situations where deallocation should behave differently than setting the variable.
I can understand eJames' argument against using property accessors in init/dealloc at all, but the flipside is that if you change the property behavior (for example, change from retain to copy, or just assign without retaining) and don't use it in init, or vice versa, the behavior can get out of sync too. If initializing and modifying an ivar should act the same, use the property accessor for both.
If so, why is this different? Is it just because the compiler can't see the ivar?
The modern runtime deals with class size and layout more intelligently, which is why you can change the layout of ivars without having to recompile subclasses. It is also able to infer the name and type of the ivar you want from the name and type of the corresponding property. The Objective-C 2.0 Runtime Programming Guide has more info, but again, I don't know how deeply the details explained there.
If I need to override an accessor, can I still access that iVar that will be defined at runtime or do I have to define an actual iVar that the runtime will then use?
I haven't tested this, but I believe you're allowed to access the named ivar in code, since it actually does have to be created. I'm not sure whether the compiler will complain, but I would guess that since it will let you synthesize the ivar without complaining, it is also smart enough to know about the synthesized ivar and let you refer to it by name.
Again, if I can access the synthesized iVar, why can't I continue to do this for the init* and dealloc methods?
You should be able to access the property and/or ivar anytime after the instance has been allocated.
There is another SO question with similar information, but it isn't quite a duplicate.
The bottom line, from the Objective-C 2.0 documentation, and quoted from Mark Bessey's answer is as follows:
There are differences in the behavior that depend on the runtime (see also “Runtime Differences”):
For the legacy runtimes, instance variables must already be declared in the #interface block. If an instance variable of the same name and compatible type as the property exists, it is used—otherwise, you get a compiler error.
For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.
My understanding is as follows:
You should not use property accessors in init* and dealloc methods, for the same reasons that you should not use them in the legacy runtime: It leaves you open to potential errors if you later override the property methods, and end up doing something that shouldn't be done in init* or dealloc.
You should be able to both synthesize the ivar and override the property methods as follows:
#interface SomeClass
{
}
#property (assign) int someProperty;
#end
#implementation SomeClass
#synthesize someProperty; // this will synthesize the ivar
- (int)someProperty { NSLog(#"getter"); return someProperty; }
- (void)setSomeProperty:(int)newValue
{
NSLog(#"setter");
someProperty = newValue;
}
#end
Which leads me to think that you would be able to access the synthesized ivar in your init* and dealloc methods as well. The only gotcha I could think of is that the #synthesize line may have to come before the definitions of your init* and dealloc methods in the source file.
In the end, since having the ivars declared in the interface still works, that is still your safest bet.
I am running into the same problem. The way I am working around not being able to access the synthesized instance variables is the following:
public header
#interface MyObject:NSObject {
}
#property (retain) id instanceVar;
#property (retain) id customizedVar;
#end
private header / implementation
#interface MyObject()
#property (retain) id storedCustomizedVar;
#end
#implementation MyObject
#synthesize instanceVar, storedCustomizedVar;
#dynamic customizedVar;
- customizedVar {
if(!self.storedCustomizedVar) {
id newCustomizedVar;
//... do something
self.storedCustomizedVar= newCustomizedVar;
}
return self.storedCustomizedVar;
}
- (void) setCustomizedVar:aVar {
self.storedCustomizedVar=aVar;
}
#end
It's not that elegant, but at least it keeps my public header file clean.
If you use KVO you need to define customizedVar as dependent key of storedCustomizedVar.
I'm relatively new to Obj-C (but not to programming) and have also been confused by this topic.
The aspect that worries me is that it seems to be relatively easy to inadvertently use the iVar instead of the property. For example writing:
myProp = someObject;
instead of
self.myProp = someObject;
Admittedly this is "user" error, but it's still seems quite easy to do accidentally in some code, and for a retained or atomic property it could presumably lead to problems.
Ideally I'd prefer to be able to get the runtime to apply some pattern to the property name when generating any iVar. E.g. always prefix them with "_".
In practice at the moment I'm doing this manually - explicitly declaring my ivars, and deliberately giving them different names from the properties. I use an old-style 'm' prefix, so if my property is "myProp", my iVar will be "mMyProp". Then I use #synthesize myProp = mMyProp to associate the two.
This is a bit clumsy I admit, and a bit of extra typing, but it seems worth it to me to be able to disambiguate a little bit more clearly in the code. Of course I can still get it wrong and type mMyProp = someObject, but I'm hoping that the 'm' prefix will alert me to my error.
It would feel much nicer if I could just declare the property and let the compiler/runtime do the rest, but when I have lots of code my gut instinct tells me that I'll make mistakes that way if I still have to follow manual rules for init/dealloc.
Of course there are also plenty of other things I can also do wrong...