Specific performance and behaviour difference using properties or accessing the ivars directly.
For Global variables, What is the difference between using this:
#interface myClass (){
UIImageView *myView;
}
-(void)loadView{
[super loadView];
myView = [[UIImageView alloc] initWithFrame:CGrectMake(0,0,100,100)];
}
And doing this:
#interface myClass (){
}
#property (nonatomic, strong) UIImageView *myView;
#synthesize myView = _myView;
-(void)loadView{
[super loadView];
myView = [[UIImageView alloc] initWithFrame:CGrectMake(0,0,100,100)];
}
What benefits can we have with every approach?
What are the reasons to recommend to always uses properties?
In the first case, your instance variable (or ivar) myView is private to the class and cannot be accessed by another class.
In the second case, you have provided a property that allows other classes to access your ivar via synthesized accessors. The alternative to declared properties is to write your own accessor methods. The #synthesize notation does that for you.
See Apple documentation on declared properties
ALWAYS create a #property for every data member and use self.name to access it throughout your class implementation.
NEVER access your own data members directly.
Here are some of the reasons to use Properties:
Properties enforce access restrictions (such as readonly)
Properties enforce memory management policy (retain, assign)
Properties are (rarely) used as part of a thread safety strategy (atomic)
Properties provide the opportunity to transparently implement custom setters and getters.
Having a single way to access instance variables increases code readability.
You can also check out: The Code Commandments: Best Practices for Objective-C Coding
Synthesize makes you getter and setter methods which are called automatically depending on whether you try read or write the value. For the myView property:
myView = newView1; // using direct ivar access
myobject.myView = newvew1; // eq [myobject setMyView:newvew1]; where setMyView: is generated for you automatically with respect to assign/retain, the same for reading:
newvew1 = myobject.myView; // newvew1 = [myobject myView:newvew1];
the generated getter/setter names are customizable with setter=/getter=, if you don't need setter use readonly.
There's no way you can forbid other classes to use synthesized getter and setter, the ivars are #protected by default and if you want to provide other classes an access to the ivars, you can declare them under #public:
#interface myClass (){
UIImageView *myView; // this is protected
#public
UIImageView *myPublicView; // this is public
}
In your first example you access your ivar directly and changing its content. In your second example (the property) an ivar has been created automatically to back the property and all your calls to set and get the property are sent as messages (like: [self setMyView:[[UIImageView alloc] initWithFrame:CGrectMake(0,0,100,100)]];). The accessor methods are also created automatically. This means that you are now following KVC/KVO protocols. For more on the benefits of this design see here
Related
This is the as to what I am trying to implement in this program
#interface settings : CBLModel
#property (copy) NSString* foo;
- (instancetype) initInDatabase: (CBLDatabase*)database withAllValues:(NSDictionary*)gameDic ChannelId:(NSString*)chann_id;
In .m file I am using this...
#implementation settings
#dynamic foo;
- (instancetype) initInDatabase: (CBLDatabase*)database
withAllValues: (NSDictionary*)gameDic ChannelId:(NSString*)chann_id
{
NSParameterAssert(gameDic);
self = [super initWithNewDocumentInDatabase: database];
if (self) {
self.foo=#"value";//this is where it crashes
}
return self;
}
-(void)setfoo:(NSString *)foo{
foo=[foo copy];//tried doin this but the value is not assigned
}
I am trying to set value of a dynamic property which results in the crash.. I need to use dynamic as I want to reflect it on server and using synthesize doesn't do that.
First of all, your property is in lowercase foo, and the dynamic declaration
in uppercase Foo. This could be a cause for problems. But assuming that this
was just a typo,
#dynamic foo;
tells the compiler that it should not synthesize getter and setter methods for the property.
It is a "promise" that the required accessor methods will somehow be provided at runtime.
Since you don't provide a setter method,
self.foo = #"abc";
must crash at runtime.
So unless you have a definite reason, you can just remove the #dynamic declaration,
and the compiler will synthesize getter, setter, and instance variable, if necessary.
A better answer might be possible if you explain what you are trying to achieve.
Remark: If your custom setFoo: goes into an infinite loop then you probably use the
property setter inside the setter method, instead of accessing the instance variable directly.
A simple example:
-(void)setFoo:(NSString *)foo
{
// wrong: self.foo = [foo copy];
_foo = [foo copy];
}
UPDATE: The above answer was written before I knew that "settings" is a subclass of
"CBLModel" from "Couchbase Lite". I do not have experience with that framework, but from
reading the documentation it seems to me that #dynamic foo; is indeed correct in this case,
and setFoo: should not be implemented in the subclass, because
the Couchbase framework creates the necessary accessor methods at runtime.
The only possible error I can see is that the custom initializer should call
self = [self initWithNewDocumentInDatabase: database];
instead of
self = [super initWithNewDocumentInDatabase: database];
Try to change #property(copy) NSString* foo; with #property (nonatomic, strong) NSString *foo;
#dynamic property indicates that implementation of setter and getter will be provided by some underlying code in runtime. It is commonly used in NSManagedObject subclasses of Core Data. There is no underlying code to manage your #dynamic properties if your object is a subclass of NSObject, so you are responsible for implementing setters and getters. Change #dynamic to #synthesize to let the compiler create appropriate setter and getter for you.
UPD: As of the latest compiler you may omit #synthesize as Martin R said.
I am trying to access an instance of SVSegmentedControl
It's a subclass of UIControl.
I created that instance during viewDidLoad
SVSegmentedControl *mySC = [[SVSegmentedControl alloc] initWithSectionTitles:[NSArray arrayWithObjects:#"Normal", #"Limosine", #"Any", nil]];
It does have a method - (void)segmentedControlChangedValue:(SVSegmentedControl*)segmentedControl { which I will be able to access the instance when the value is changed. But how do I access the instance(mySC) at other parts of the code?
Set a property in your UIViewController, and instead of creating a new instance variable, set the property to the newly initialised segmented controller. And from there on you can access it outside the viewDidLoad's scope.
Edit...
You really need to learn how to propertize / setter & getter a variable rather than asking people to post code for you.
Below the } in the header file:
#property (nonatomic, retain) SVSegmentedControl *control;
Top of the implementation file
#synthesize control;
To set it:
self.control = [[[SVSegmentedControl alloc] init...] autorelease];
It should be set to nil in the dealloc method.
If I have a custom NSObject class called ProgramModel, does it get alloc/init -ed when I #property and #synthesize it from another class?
For instance, in a ProgramController class like this
// ProgramController.h
#import "ProgramModel.h"
#interface ProgramController : UIViewController {
ProgramModel *programModel;
}
#property (nonatomic, retain) ProgramModel *programModel;
// ProgramController.m
#import "ProgramController.h"
#implementation ProgramController
#synthesize programModel;
// etc
Do I also need to alloc/init in the initWithNibName or viewDidLoad, or is it already alloc/init-ed because of the property/synthesize?
You need to populate the property manually. The exception is if you have an IBOutlet property that you've connected in a nib file; that will get populated automatically when the nib is loaded.
I find that for view controllers the vast majority of properties are IBOutlets and properties that describe what the view will show, and the latter case is usually set by the object that creates the view controller. That will usually be the case for a view controller that shows a detail view for some object.
If you do have properties that are completely local to the view controller, a common pattern is to write your own getter and setter (rather than using #synthesize) and create the object in the getter if it doesn't exist. This lazy-loading behavior means you can easily free up resources in low-memory conditions, and that you only pay the cost of loading an object when you need it.
// simple lazy-loading getter
-(MyPropertyClass*)propertyName {
if(propertyIvarName == nil) {
propertyIvarName = [[MyPropertyClass alloc] init];
// ... other setup here
}
return propertyIvarName;
}
By default, all instance variables are zero'd out. In the case of objects, that means they're nil. If you want an initial value in the property, you need to put it there during your initializer/viewDidLoad method.
#property only declares the getter/setter methods.
#synthesize only generates the accessors for you.
They are not automatically assigned values, apart from the memory being zeroed. Additionally, you have to set them to nil in -dealloc to avoid a leak.
It also doesn't make sense to "alloc a property". An object property is a pointer. (And think of what happens if you have a linked list class...)
(N.B.: The property attributes also affect the #synthesized method, and the properties are also known to the runtime; see class_copyPropertyList() and friends.)
What do #synthesize and #property do in Xcode? Please provide an explanation in really simple terms?
You asked for simple terms:
#property declares a property in your
class header
#property (nonatomic, retain) NSString *myString;
#synthesize creates your setter and
getter for your property (accessor
methods)
Without synthesize you have to write
your own setter and getter
implemention, like getMyString or
setMyString (capitalize the first
character of your property)
Sam: Just an advice: http://www.cocoadevcentral.com/d/learn_objectivec/ is a pretty solid resource to learn about basics like properties.
Good Luck!
Properties and synthesized accessors are new features in Objective-C 2.0.
When you declare a #property you declare somewhat an instance var. Then you #synthesize accessor methods (i.e. getter and setter) for that property.
There are also #dynamic accessors if you're interested.
You should really do your homework on this. Apple has nifty pdf for that.
Think of all objective-c magic as just a "smarter macro", like a "smarter #define statement"
#property if you notice is always in the h file,
#synthesize is always in the m file.
So in the background
#property (whatever) NSString *myString;
becomes a declaration of 2 methods and a private variable;
void set_myString:(NSString *) str;
(NSString*) get_myString;
declarations in the header file
to make them do something their implementation is added into m file when you type in
#synthesize myString;
which becomes something like
void set_myString:(NSString *)str
{
myString = str;
}
(NSString *) get_myString
{
return (myString);
}
But it's smarter than this
depending on if you say "retain" "strong" or "weak"
it will either just return the pointer to the myString or it will copy the myString into a new object
So all of this is done automatically by a compiler just by reading your declarations.
Which is quite useful and saves a lot of time
By default all our variables are Private so we can't acess out of the class.
if we want to use our instance variable in out of the class.
When you declare a #property you declare somewhat an instance var. Then you #synthesize accessor methods (i.e. getter and setter) for that property.
There are also #dynamic accessors if you're interested.
it simply sets the property's setter variable name in it's own class.
For example lets say I have this: #property (nonatomic, copy) NSArray* viewControllers;
Well if i want to access the setter _viewController i wouldn't set a synthesize variable.
but if i want to access the viewController variable by the name viewController instead of _viewController, I would do #synthesize viewController;.
If I wanted to use it as a completely different name I could do this #synthesize viewControllers = viewControlololer; but that's only setter. As you will notice [self viewControllers] only works and not [self viewControlololer];
So I don't understant why everyone writes sets the "setter and getter" of a property. It doesn't change the getter variable at all... unless that means [self viewController] is aware of viewControlololer (obviously).
Actually properties are synthesized, either implicitly or explicitly. Properties are implicitly synthesized. So there's no need to use synthesized unless you wanna change the name of the variable to something different than _property_name.
There are other use cases, for example if you don't want an instance variable to back your property.
Properties are explicitly synthesized by using the #synthesized directive.
(Answer extracted from the Big Nerd Ranch guide)
Sorry I couldn't give a more descriptive title. My question (after looking at the code below) is what statusText is. Is it an IBOutlet or a UILabel? How does "#property (retain,nonatomic) UILabel *statusText" work? Does that statement mean that statusText is a property???
Thanks for answering. If there are any questions, please feel free to comment.
Button_FunViewController.h
#interface Button_Fun2ViewController : UIViewController {
IBOutlet UILabel *statusText;
}
#property (retain,nonatomic) UILabel *statusText;
- (IBAction)buttonPressed: (id)sender;
Button_FunViewController.m
#synthesize statusText;
- (IBAction)buttonPressed: (id)sender {
NSString *title = [sender titleForState:UIControlStateNormal];
NSString *newText = [[NSString alloc] initWithFormat:#"%# button was pressed.", title];
statusText.text = newText;
[newText.release];
}
IBOutlet evaluates to nothing, it's just a hint to Interface Builder that it's a 'connection'.
And yes, statusText is a property then. There are three statements needed for a property (on a non-"modern runtime" system) – an ivar declaration, a #property statement, and a synthesize statement.
statusText is an instance variable of type UILabel*. The IBOutlet keyword simply makes that instance variable available to Interface Builder.
#property declares accessor and/or mutator methods for the given property. It's equivalent to declaring -statusLabel and -setStatusLabel: methods.
You can use #synthesize to automatically implement these -statusLabel and -setStatusLabel: methods. The nonatomic and retain keywords define the behaviour of these automatically-generated methods.
Alternatively, you can implement the -statusLabel and -setStatusLabel: methods yourself.
what is statusText ?
statusText is a UILabel in your code example
Is it an IBOutlet or a UILabel?
Both.
UILabel is a type (a pointer to UILabel component that you use in GUI)
IBOutlet marks variable for Interface Builder application, so that it knows to show it as Outlet. During compilation IBOutlet is compiled out, it is defined in NSNibDeclarations.h as:
#define IBOutlet
How does #property
(retain,nonatomic) UILabel
*statusText work?
You can create accessors (getters/setters) for a variable by hand, no need to use property. You can just have UILabel *statusText and implement your getter/setters by hand.
You can have accessors declared by compiler by defining variable as a #property and then either use #synthesize to create accessors in .m file or again you declare the accessors yourself (you can override default accessors that would be generated)
You can have readwrite or readonly property - meaning either both setter and getter gets generated or only getter.
You can use copy, retain or assign for setter (see more about memory management about the tree optons copy/retain/assign)
There are some other options like nonatomic/atomic which has to do with generating mutexes and lock variable before access and so on (see more about properties)
For example if you have variable
NSString * string;
defining it as readwrite property and then synthesising you get the compiler to generate for you:
#property (copy, readwrite) NSString * string
then using
#synthesize string;
generates something like:
- (NSString *) string
{
return string;
}
- (void)setString:(NSString *)str
{
NSString * copy = [str copy];
[string release];
string = copy;
}
Does that statement mean that
statusText is a property???
Yes you defined it as a property as explained above.
There are couple of concepts involved here.
Definition of variable, defining it as IBOutlet for Interface Builder, declare variables as properties so that compiler generates getters/setters for you, defining type of getters/setters such as access method, memory management and locking.
I hope this explains your questions and if you follow the link you will find the explanation by Apple which I believe is quite clear about how to use properties.
Sorry for the horrible formatting ...
If you put IBOutlet in there like that, it will allow you to link the item while you're in interface builder.
Once you have the IBOutlet setup, you can open that class's nib and then select the File's Owner, then go to the inspector and drag a link from the Connections tab to the object.
This let's you then make changes to the object in your class's code and it will change the linked object. So once you link "statusText" to a specific UILabel, you can then use statusText.text = #"new text" in your class's code to modify the item, for example.
Also, IBAction allows you to make links in the same way. You can drag a connection from a control's event to the file owner and then select any method within that class that has IBAction as a return value.
There are in fact two statusText "things" in your example. There is a statusText object of type UILabel, and there is a statusText function created by #synthesize. When you use statusText from inside a method you are reffering to the object, not the function. Use self.statusText to use the property/function.