Why do I declare a #property when I can use an inline variable instead? - objective-c

I have spent a few days learning Objective-C and have a few questions about #property. I have experience with C# so understand the need for pointers, initialization etc.
So as an example:
#interface MyClass : NSObject
{
IBOutlet UIImageView *image;
}
#property (retain, nonatomic) UIImageView *image
#end
#implementation MyClass
#synthesise image
#end
I understand that #synthesise is used to create the #property. But I have a few questions just to help me clear things up:
Does the #property duplicate or replace my original definition, or does it merely set up the mutibility and atomicity of the original?
Does #synthesise remove my need to use image = [[UIImageView alloc] init]?
If I do not provide a #property and still go ahead creating and destroying my variable manually, does that make any difference?
Ultimately, is the difference between the 2, #property gives you more flexibility with regards to memory management and multi-threading and the normal one gives you the defaults.

Does the #prototype duplicate or replace my original definition, or does it merely set up the mutibility and atomicity of the original?
The ivar declaration of image is redundant when using the most recent compiler releases.
The former declares an ivar (type + name + instance storage).
The property declaration specifies the type, name, storage (in more recent compiler releases), declares the accessor methods (e.g. - (UIImageView *)image; and - (void)setImage:(UIImageView *)pImage;), and other property specifiers (which are used when the accessors are generated by the compiler).
Does #synthesise remove my need to use image = [UIImageView alloc]?
No. You still need to implement your initializer and dealloc (in MRC) appropriately.
If I do not provide an #property and still go ahead creating and destroying my variable manually, does that make any difference?
That would be fine, when you do not want/need boilerplate accessor methods generated for you. It's a design choice. Not every ivar needs accessor methods.
Ultimately, is the difference between the 2, #property gives you more flexibility with regards to memory management and multi-threading and the normal one gives you the defaults.
The biggest reason they exist is convenience. Properties save a lot of boilerplate code.
There is no more flexibility with properties -- properties implement the most practical uses.
It's infrequent that atomicity (in this context) is equivalent to proper thread safety and correct concurrent execution.

1) The property does not replace the class member. A property is a declaration that you want the accessors (getter and setter) for a class member to perform certain "automatic" tasks and have a certain name.
For example:
#interface MyClass : NSObject
{
NSInteger __myInt;
}
#property (assign) NSInteger myInt;
#end
#implementation MyClass
#synthesize myInt=__myInt;
#end
The above code, for all intents and purposes, is causing the following methods to be automatically generated at compile time:
-(NSInteger) myInt
{
return self->__myInt;
}
-(void) setmyInt:(NSInteger)val_
{
self->__myInt = val_;
}
Of course, what happens "in the background" when Xcode compiles your program is a bit different and more nuanced, but this is basically what happens.
2) I'm not entirely clear what you mean by this one... You always need to alloc and init your variables, regardless of accessor synthesis.
3) No. Properties/synthesis are only needed for a) convenience, be it syntactic or atomicity for multithreading, and b) external access to members inside your class.
EDIT:
To clarify on multithreading and properties, declaring a property nonatomic does a great deal for thread safety. This, and my response to #3, addresses your last concern in your question.

You can do this:
#interface MyClass : NSObject
#property (retain, nonatomic) IBOutlet UIImageView *image;
#end
#implementation MyClass
#synthesize image;
#end
Does the #prototype duplicate or replace my original definition, or does it merely set up the mutibility and atomicity of the original?
The property adds things on-top of the ivar like KVO and thread safety if it's atomic.
Does #synthesise remove my need to use image = [UIImageView alloc]?
No
If I do not provide an #property and still go ahead creating and destroying my variable manually, does that make any difference?
If you don't make a property you lose out on the things a property gets you like KVO, it's a judgment and api call on how the variable will be used. Under arc it is much easier to use straight up ivars because you don't have to replicate the retaining and releasing the property did automatically.

The 'image' in #property (retain, nonatomic) UIImageView *image line is just a name of the property and IBOutlet UIImageView *image; is an ivar which you access through self.image. I always name an ivar for property the same as the name but add _ :
UIImage * image_;
#property (retain, nonatomic) UIImageView *image;
#synthesize image = image_;
If you will not create an ivar for your property the Xcode do it automatically for you (the name of the ivar will be the same as the name of property)

Related

Objective-C: Compiler error when overriding a superclass getter and trying to access ivar

I'm working on building an iOS 6 app.
I have a class TDBeam which inherits from superclass TDWeapon.
The superclass TDWeapon declares a #property in the TDWeapon.h file:
#interface TDWeapon : UIView
#property (nonatomic) int damage;
#end
I do not explicitly #synthesize the property, as I'm letting Xcode automatically do so.
In the subclass TDBeam I override the getter in the TDBeam.m file:
#import "TDBeam.h"
#implementation TDBeam
- (int)damage {
return _damage;
}
#end
Xcode auto-completes the getter method name, as expected. But when I attempt to reference the _damage instance variable (inherited from the superclass), I get a compiler error:
Use of undeclared identifier '_damage'
What am I doing wrong here? I've tried explicitly adding #synthesize, and changing the name of the _damage ivar, but the compiler doesn't "see" it or any other ivars from the superclass. I thought ivars were visible and accessible from subclasses?
Synthesized ivars are not visible to subclasses, whether they are explicitly or automatically created: What is the visibility of #synthesized instance variables? Since they are effectively declared in the implementation file, their declaration isn't included in the "translation unit" that includes the subclass.
If you really want to access that ivar directly, you'll have to explicitly declare it (in its default "protected" form) somewhere that the subclass can see it, such as a class extension of the superclass in a private header.
There are a lot of posts on this topic on Stack Overflow, none of which offer simple concrete advice, but this topic sums it up most succinctly, and Josh's answer is the best in any.
What he kinda stops short of saying outright, is, if this is the kind of thing you want to do, don't use #property at all. Declare your regular protected variable in your base class as he says, and write you're own setters and getters if you need them. The ivar will be visible to any subclasses who can then write their own setters/getters.
At least that's where i've landed on the issue, although I'd a total newb to subclassing.
The idea of creating private headers to host your anonymous category and re-#sythesizing your ivars in your subclass just seems wrong on so many levels. I'm also sure I've probably missed some fundamental point somewhere.
Edit
Okay after some lost sleep, and inspired by Stanford's 2013 iTunes U course, here I believe is an example solution to this problem.
MYFoo.h
#import <Foundation/Foundation.h>
#interface MYFoo : NSObject
// Optional, depending on your class
#property (strong, nonatomic, readonly) NSString * myProperty;
- (NSString *)makeValueForNewMyProperty; //override this in your subclass
#end
MYFoo.m
#import "MYFoo.h"
#interface MYFoo ()
#property (strong, nonatomic, readwrite) NSString * myProperty;
#end
#implementation MYFoo
// Base class getter, generic
- (NSDateComponents *)myProperty {
if (!_myProperty) {
_myProperty = [self makeValueForNewMyProperty];
}
return _myProperty;
}
// Replace this method in your subclass with your logic on how to create a new myProperty
- (NSString *)makeValueForNewMyProperty {
// If this is an abstract base class, we'd return nil and/or throw an exception
NSString * newMyProperty = [[NSString alloc]init];
// Do stuff to make the property the way you need it...
return newMyProperty;
}
#end
Then you just replace makeValueForNewMyProperty in your subclass with whatever custom logic you need. Your property is 'protected' in the base class but you have control over how it is created, which is basically what you are trying to achieve in most cases.
If your makeValueForNewMyProperty method requires access to other ivars of the base class, they will, at the very least, have to be be public readonly properties (or just naked ivars).
Not exactly 'over-ridding a getter' but it achieves the same sort of thing, with a little thought. My apologies if, in trying to make the example generic, some elegance and clarity has been lost.

concept of instance properties

would you please break my confusion.
If I define a property in a class
#interface Class
{
UIScrollView * _scrollView;
}
#property (nonatomic, retain) IBOutlet UIScrollView * scrollView;
#end
#implement
#synthesize scrollView = _scrollView;
#end
When I wanna implement it, I can use
_scrollView.contentSize = xxx
or
self.scrollView.contentSize = xxx
What's the difference between the two description?
Thanks for your answering...
The direct reference to the instance variable is precisely that -- a reference to a field in the instance, unaffected by the fact that it's also the "backing store" of a property.
The self.propName reference, on the other hand, is shorthand for either [self propName] (if reading) or [self setPropName:newPropValue] (if setting). Ie, those references go through accessor methods. This isn't real important if the property is defined as assign, but if it's retain then the setter method takes care of all the retain logic.
Further, you can implement your own property accessors -- -(SomeType*) propName {...} and -(void) setPropName:(SomeType*)propParm {...} -- if you want to have them do something special, such as "lazy" initialization.
(Also, properties default to "public" access, while instance variables default to "private" access.)

Subclass Properties

I'd like to do the following, in an abstract way:
// .h
#interface SomeObject : NSObject
#property (readonly) NSArray myProperty;
#end
// .m
#interface SomeObject ()
#property (readwrite) NSMutableArray myProperty;
#end
#implementation SomeObject
#end
According to the section Subclassing with Properties in the Mac Developer Library it is allowed to overwrite readonly properties with readwrite. What doesn't work is using a subclass for the property type. I used NSMutableArray as an example, but it could be any other class/subclass combination.
According to inheritance rules, it should be ok though. readonly just generates the getter which also is allowed to return a subclass object.
How do you tackle such cases when you need a subclass type for some property for internal use?
An ugly way would be the following, but I'd like to avoid that as it means that I cannot use the self. getters and setters when accessing subclass methods.
// .h
#interface SomeObject : NSObject
#property (readonly) NSArray myProperty;
#end
// .m
#implementation SomeObject {
NSMutableArray _myProperty;
}
#synthesize myProperty = _myProperty;
#end
EDIT (based on your edits): Your specific case after the edit is a somewhat special and common case (if it can be both at the same time), and requires some careful consideration.
The reason this is a special is because the subclass is a mutable form of the exposed class. The caller may expect that it will not change after receiving it. But if you hand back your internal object, then it might mutate. You have several options:
Return an immutable copy. This is often the best solution for small collections. It's certainly the simplest. But if the accessor may be called often and the collection is large, it can be prohibitively expensive.
Make your internal property immutable. If requests for the property are much more common than changes to the property, it can be more efficient to recreate the object when it mutates (using arrayByAddingObject:, subarrayWithRange: and the like).
Warn the caller that the object being returned may change.... uggh... I've done this in one case where I needed the performance, but it's quite dangerous.
I've never actually done it this way, but you could also create your own copy-on-write this way: Return the mutable version directly and mark a flag that it is now "dirty." When mutation is required internally, make a mutable copy and store it in your property (letting go of the old collection). This seems a lot of complexity, but might be useful for some situations, particularly if reads and writes tend to clump separately (lots of reads followed by lots of writes).
OLD ANSWER based on NSObject vs. NSString:
I assume your goal here is to make myProperty be of some opaque type, rather than leaking the fact that it is an NSString? Perhaps so you can change your mind later on how it's actually implemented? There are a few options. The easiest is to define it of type id. Then internally just treat it as a string. id can be anything. It is usually preferred over NSObject*.
If you want more type-safety internally, then you can create a private property with another name of type NSString and return it for myProperty like this:
SomeObject.h
#interface SomeObject : NSObject
#property (readonly) id myProperty;
#end
SomeObject.m
#interface SomeObject ()
#property (readwrite) NSString *myInternalProperty;
#end
#implementation SomeObject
- (id)myProperty {
return myInternalProperty;
}
#end
Another hiding technique you can use (if hiding is very important to you) is a subclass. For example:
SomeObject.h
#class MyOpaque;
#interface SomeObject : NSObject
#property (readonly) MyOpaque *myProperty;
#end
SomeObject.m
#interface MyOpaque : NSString
#end
#implementation MyOpaque
#end
#implementation SomeObject
#end
Since the caller does not have an #interface definition for MyOpaque, he can't send messages to it without a compiler warning.
How do you tackle such cases when you need a subclass type for some
property for internal use?
Properties are explicitly not for internal use, they are members of a public interface.
If you need an internal value define a member field and override the setter of the property to set your internal value.

Features of use #property and #synthesize (cocos2d)

I saw in the libraries for use cocos2d strange #property and #synthesize
Standard in the examples is written as follows:
in .h
CGFloat minimumTouchLengthToSlide;
}
#property(readwrite, assign) CGFloat minimumTouchLengthToSlide;
in .m
#synthesize minimumTouchLengthToSlide
But in lib https://github.com/cocos2d/cocos2d-iphone-extensions/tree/master/Extensions/CCScrollLayer and another libs\extensions
in .h
CGFloat minimumTouchLengthToSlide_;
}
#property(readwrite, assign) CGFloat minimumTouchLengthToSlide;
in .m
#synthesize minimumTouchLengthToSlide = minimumTouchLengthToSlide_;
What is the meaning of this code?
Why they changed minimumTouchLengthToSlide to minimumTouchLengthToSlide_ and added minimumTouchLengthToSlide = minimumTouchLengthToSlide_;
Its often considered good practice to name the instance variable different from the property. The resoning behind this is that in that case you cannot accidently use the instance variable instead of the property. This is not that important when using value types such as integers and floats but more important when using reference types on retain properties. Consider a property
#property (nonatomic, retain) NSString *myString;
...
#synthesize myString;
The compiler takes care of retaining the string when you do self.myString = someString. But when you write myString = someString you do not actually use the property but rather the variable directly and no retaining will take place. This can lead to zombies, leaks etc. By giving the instance variable a different name like this:
#property (nonatomic, retain) NSString *myString;
...
#synthesize myString = myString_;
you can no longer write myString = someString because this would issue a compiler error. If you needed to use the instance variable directly you could always write _myString = someString but in practice this is rarely needed.
There are other cases when you write explicit property methods but the issue is basically the same, you cannot accidently bypass the property methods when using the second variant.
So basically this is a method to avoid unnecessary errors when handling properties (mostly retain-properties).
#property and #synthesize are a really cool feature of Objective-C to allow the automatic creation of getter and setter methods. In your examples they would create:
- (CGFloat)minimumTouchLengthToSlide and
- (void)setMinimumTouchLengthToSlide:(CGFloat)newLength; for free.
#synthesize minimumTouchLengthToSlide = minimumTouchLengthToSlide_ means they are telling Objective-C that when someone tries to access that property, then it should point at the instance variable minimumTouchLengthToSlide_
readwrite,assign describe what happens when someone sets the property. Assign means that the value is not retained, the variable is just pointed. An example of what that method might look like could be this:
- (void)setMinimumLengthToSlide:(CGFloat)newLength {
[self willChangeValueForKey:#"minimumLengthToSlide"]; // let observers know this property is changing
minimumLengthToSlide_ = newLength;
[self didChangeValueForKey:#"minimumLenghtToSlide"];
}
You can read more about them here.

Do I need to declare a property in the instance variables section, too? What do I gain?

I read some tutorials here about properties ,but i still have some doubts to clarify, is there a difference between
#interface MyClass : NSObject {
}
#property(nonatomic,retain) NSString *temp;
#end
AND
#interface MyClass : NSObject {
NSString *temp;
}
#property(nonatomic,retain) NSString *temp;
#end
The difference is that in the first version, the compiler will automatically create an instance variable (IIRC, it will be named _temp but I don't know for sure). This is only supported on iOS and Mac 64 bit.
In the second example, you provide the variable.
There's actually a way to tell the compiler which variable to use for the property, which I use a lot:
#interface MyClass : NSObject {
NSString *temp_;
}
#property(nonatomic,retain) NSString *temp;
#end
#implementation MyClass
#synthesize temp = temp_;
#end
This way the variable and the property have different names and you can't confuse them (e.g. by forgetting to prefix self.).
Minor side-note: it's often desirable to use copy instead of retain for NSString *, since you might assign an NSMutableString * to the property. Now if you would change that mutable string unexpected things might happen.
Does the first one even work? If there is no instance variable its a bit hard to have a property to access it.
#properties are meant for you, so you can be lazy, they write the following 2 methods for you ( if not set to readonly ):
- (void)setYourVariable:(id)new;
- (id)yourVariable;
it also allows you to use "someClass.itsVariable;" instead of "[someClass itsVariable];"
Another thing, when you create your header files make sure that the biggest variables ( like pointers ) are on the top and the smallest on the bottom, this saves ram.
thus:
NSObject *someObject;
NSObject *someOtherObject;
int anInt;
short aShort;
BOOL fakeBool;
instead of:
BOOL fakeBool;
NSObject *someObject;
short aShort;
NSObject *someOtherObject;
int anInt;
This has to do with the compiler, you can check this by using sizeof()
In the modern runtime (Objective-C 2.0) it is the same because the compiler will generate the variable for you. See Question about #synthesize
Quoting The Objective-C Programming Language > Declared Properties > Property Implementation Directives:
There are differences in the behavior of accessor synthesis that
depend on the runtime:
For the legacy runtimes, instance variables must already be declared in the #interface block of the current class. If an instance
variable of the same name as the property exists, and if its type is
compatible with the property’s type, 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.
The practical difference that I've found is that the debugger doesn't appear to show you the value of properties, just instance variables.
Therefore, your first example, which (assuming you use the #synthesize directive to create your getter/setter) automatically creates the ivar, will not have a value that you can easily retrieve during debug. You'll end up having to send a lot of NSLog messages, rather than just looking at the values while stepping through your code.
As an aside, which seems to relate to this topic, I typically prepend my ivars with "iv" and change my color settings in XCode preferences so that I'm never unsure whether I'm accessing a property or an ivar.
Example
#interface MyClass : NSObject {
NSString *ivName;
NSString *ivTitle;
}
#property (nonatomic, copy) NSString *Name;
#property (nonatomic, copy) NSString *Title;
#end
Now, this then requires a small trick (to tie the two together) when synthesizing the properties, which I show below:
#implementation MyClass
#synthesize Name = ivName;
#synthesize Title = ivTitle;
This way, it's always very easy for me to know exactly what's going on at a glance. Yes, context can also tell you whether you're accessing an ivar/property, but why not make it easier?