A few times already I wanted to make a property, which is nonatomic and readonly at the same time.
This has the advantage that I can override the getter and check if an instance has already been created or not. And if not I can simply create it.
At the same time I can protect it from being overwritten.
.h
#property (strong, readonly, nonatomic) Foo *bar;
.m
- (Foo *)bar {
if (!_bar) {
_bar = [[Foo alloc] init];
}
return _bar;
}
Whenever I do this, the compiler doesn't create an instance variable for me, so _bar doesn't exist.
Why? How can I create a readonly nonatomic property?
Your property declaration is correct. I believe the problem here is that, because your property was declared as readonly, the compiler didn't automatically synthesize an underlying instance variable. The solution in this case is to synthesize one yourself using...
#synthesize bar = _bar;
You could create a private setter:
#interface YourClass() // In the .m file
#property (strong, readwrite, nonatomic) Foo *bar;
#end
Then when assigning the variable:
self.bar = [[Foo alloc] init];
EDIT
Mark Adam's answer is also correct.
In the implementation add #synthesize bar = _bar.
Related
Sorry for the simple question.
When I see a definition of a property inside the h file, but outside of the class #interface scope, what does it mean ?
#property (nonatomic, readonly) RMMapContents *mapContents;
Here is the code:
#class RootViewController;
#class RMMapContents;
#interface MapTestbedAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
//MAIN VIEW
//==============
RootViewController *rootViewController;
// NETWORK DATA
// =============
NSMutableArray *photoTitles; // Titles of images
NSMutableArray *photoSmallImageData; // Image data (thumbnail)
NSMutableArray *photoURLsLargeImage; // URL to larger image
NSMutableData *receivedData;
NSURLConnection *theConnection;
NSURLRequest *request;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet RootViewController *rootViewController;
#property (nonatomic, readonly) RMMapContents *mapContents;
#end
Inside a function I see this line:
- (void)foo:(xyz *)abc{
..
RMMapContents *mapContents = [self mapContents];
..
}
So, taking it from C++, the mapContents seem like it is not a global scope var (after all, that's why they call them properties, right?), but isn't defining the same name again inside the function weird a bit?
I hope someone can clarify a little here.
Thanks!
The scope of the #interface block extends upto the #end keyword and is not restricted to the braces {}.
So the #property declaration lies very much inside the scope of the #interface and like cli_hlt rightly answered, it acts like a substitute to setter and getter methods for the mapContents property.
so a property named mapContents, would have setters and getters which look like this :
- (void)setMapContents; //setter
- (RMMapContents *)mapContents; //getter
and would can be accessed from within the class using these methods:
[self setMapContents:newContents];
AND
RMMapContents *contents = [self mapContents];
Well, a property is not just a variable. A property is a variable plus its setter and getter methods. A property is usually said to be backed by a variable, which usually(but not always) has the same name as the property itself.
So there are basically three scenarios:
The developer has redefined the backing variable, look for something like:#synthesize mapContents=mapContents_, at the beginning of the implementation -> no problem here.
The compiler defined the variable to be something you don't now but not equal to mapContents - > no problem.
The property backing variable is indeed called "mapContents", so then the local definition hides the global definition (look for a compiler warning here). But by calling [self mapContents] you will not access the global variable but call the getter, which in turn will access the class variable (because then the local mapContents is out of scope)
Hope this helps.
global var mapContents is readonly,in foo function , create a new pointer,then you can change the value of inner var.
Look for a method in your class with a name mapContents that will return a initialization to your RMMapContents class.
Basically this line RMMapContents *mapContents = [self mapContents]; says that initializing an instance of RMMapContents called mapContens using the method mapContents.
I've kind of been confused about properties. Some people say to always use setters and getters for ivars, even within the ivar's class. So if "name" is an ivar, when referring to it, one should always use "self.name". Always. Even if you're in the same class that "name" is declared in.
First, is that correct advice?
Second, what if I wish to reap the automatic memory management that comes with declaring "name" as a property and synthesizing it, but I don't want to give other classes access to change "name"? I guess it would be sort of a private property?
Thanks!
Yes, you should always try to use the property accessors when possible. Using ARC alleviates these concerns somewhat, but it's still good style. As for your second question, you can declare the property as readonly in the public header file and redefine it in a class extension:
In MyClass.h:
#interface MyClass : NSObject
#property (strong, readonly, nonatomic) id foo;
#end
In MyClass.m:
#interface MyClass()
#property (strong, readwrite, nonatomic) id foo;
#end
#implementation MyClass
#synthesize foo = _foo;
// The rest of your code goes here.
#end
This will allow you to call [self setFoo:foo] all day inside of MyClass’s implementation, but not other classes.
For ivars which are accessed externally, I generally use properties to access the ivar from within the class, for ivars which are only used internally (usually BOOL, NSUInteger, NSInteger, etc), I use the ivar directly. I do however access an consistently within the class (i.e. if I'm using a property to access it, I always use a property).
For the second part of your question. You can create a readonly property in the class's interface definition and within the same file as the implementation create a category with the read-write property. For example:
MyClass.h
#interface MyClass : NSObject
{
NSString * name;
}
#property (nonatomic, readonly) NSString * name;
#end
MyClass.m
#interface MyClass()
#property (nonatomic, retain) NSString * name;
#end
#implementation MyClass
#synthesize name;
-(void)dealloc
{
[name release];
[super dealloc];
return;
}
#end
Keep in mind, that although another class accessing the method -setName: may cause compile warnings or errors, another class may still call -(id)performSelector:withObject: with without an error.
For instance:
MyClass * test = [[MyClass alloc] init];
test.name = #"David";
is functionally the same as:
MyClass * test = [[MyClass alloc] init];
[test performSelector:#selector(setName:) withObject:#"David"];
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Prefixing property names with an underscore in Objective C
I just started iphone App development and noticed that when you generate a new project, the following code can be seen in AppDelegate.m
#synthesize window = _window;
#synthesize viewController = _viewController;
AND in the AppDelegate.h file it says
#property (strong, nonatomic) UIWindow window;
#property (strong, nonatomic) ViewController controller;
I would just like to know what exactly this means, particularly the synthesizing part. Is it
instantiating a local private variable? If so, how is this different from saying
#synthesize viewController;
Thanks
The pattern #synthesize foo = bar; allows you to define a property of key foo which gets synthesized in combination with an instance variable of name bar (or _foo if you want), while #synthesize foo; simply synthesizes a property and instance variable with the same name (foo that is).
#property (...) Foo *foo;
#synthesize foo = _foo;
is kind of equivalent to this:
#interface MyClass : NSObject {
//result of #synthesize...:
Foo *_foo;
}
//result of #property...:
- (void)setFoo:(Foo *)foo;
//result of #property...:
- (Foo *)foo;
#end
#implementation MyClass
//result of #synthesize...:
- (void)setFoo:(Foo *)foo {
_foo = foo; //simplified!
}
//result of #synthesize...:
- (Foo *)foo {
return _foo; //simplified!
}
#end
The synthezised instance variable would the be used via either _foo or self->_foo (of which the former actually is an implicit form), which would involve no accessor method call whatsoever.
While the synthezised property would the be used via self.foo, which would then utilize a call to one of the synthesized accessor methods.
Just think of #synthesize foo; as an implicit #synthesize foo = foo; (note the lack of an _ here, equal names).
More or less. These lines in the .h declare the existence of two public variables called window and controller:
#property (strong, nonatomic) UIWindow window;
#property (strong, nonatomic) ViewController controller;
But these lines only declare the existence of the variables, they don't actually create them. It's up to the class to implement these however it wants - they could be virtual variables for example, that don't actually exist but call methods that create data programmatically, or load it from a database or something.
These lines in the .m file actually create ("synthesize") the variables.
#synthesize window = _window;
#synthesize viewController = _viewController;
What these lines actually say is that the internal variable name is _window, but the public name of the variable is window. That means that within the class you can access the variable directly by saying
_window = something;
But externally you have to access it using
appDelegate.window = something;
Because that's it's public name. You can also access it internally to the class using self.window.
Another interesting fact of Objective-C is that using dot syntax to access variables in this way is really just a handy way of calling setter and getter methods to access them. SO the synthesize line, in addition to creating a variable called _window, is also defining the following two methods:
- (void)setWindow:(UIWindow *)window; // to set the _window variable
- (UIWindow *)window; // to get the _window variable
And you can call these methods directly if you like, using
[self setWindow:someValue];
UIWindow *window = [self window];
There are 3 modifiers: #private, #protected (default) and #public. So if i define a instance variable as private then that should not be accessible from anywhere.
For E.g. -
#interface A {
#private
NSString *a;
}
#property(nonatomic, retain) NSString *a;
Now inside implementation of some other interface/class B-
-(void)getSomeValue {
A *object = [[A alloc] init];
NSString *value = object.a;
.........
}
Here i am able to access instance variable, although i defined that as private.
It is a bit confusing, although when i look into details of this statement, then it is clear that it is calling the getter of a, but then also it seems confusing and it is against the concept of OOPS.
Anyone having any thought on this?
It's not the instance variable you're accessing but the property you declared. Don't declare the property if you do not want the instance variable to be visible outside the class.
#import <Foundation/Foundation.h>
#interface Visibility : NSObject {
#public
BOOL boolPublic;
#protected
BOOL boolProtected;
#private
BOOL boolPrivate;
}
#property (nonatomic, assign) BOOL boolPublic;
#property (nonatomic, assign) BOOL boolProtected;
#property (nonatomic, assign) BOOL boolPrivate;
#end
#implementation Visibility
#synthesize boolPublic;
#synthesize boolProtected;
#synthesize boolPrivate;
#end
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Visibility *visibility = [[Visibility alloc] init];
visibility.boolPublic = YES;
visibility.boolProtected = YES;
visibility.boolPrivate = YES;
// Place following NSLog()'s here
[pool release];
}
Let's try this out
Using the methods you define with #property/#synthesize
NSLog(#"Accessors %d %d %d", visibility.boolPublic, visibility.boolProtected, visibility.boolPrivate);
=> 2012-01-08 17:46:40.226 Untitled[2592:707] Accessors 1 1 1
Accessing #public ivar directly
NSLog(#"Public %d", visibility->boolPublic);
=> 2012-01-08 17:46:40.228 Untitled[2592:707] Public 1
Accessing #protected ivar directly
NSLog(#"Protected %d", visibility->boolProtected);
=> error: instance variable 'boolProtected' is protected
=> NSLog(#"Protected %d", visibility->boolProtected);
=> ^
Accessing #private ivar directly
NSLog(#"Private %d", visibility->boolPrivate);
=> error: instance variable 'boolPrivate' is private
=> NSLog(#"Private %d", visibility->boolPrivate);
=> ^
When you are accessing using dot notation this:
visibility.boolPublic
is equivalent to:
[visibility boolPublic]; // <- This is a method call
Because you set it as a #property and you claim it in header file. The variable you set as a #property will auto generate getter and setter for this variable and they are both public method to get or set it(variable is still private). If you really want to make the property as an private method, you should claim it in .m file and it will become private. You can only use this variable in the .m file.
For example, in your .h file
#interface ClassWithPrivateProperty : NSObject {
#private
NSString* member;
}
- (void) trySettingPrivateProperty;
#end
in your .m file
#import "ClassWithPrivateProperty.h"
#interface ClassWithPrivateProperty ()
#property (nonatomic,retain) NSString* member;
#end
#implementation ClassWithPrivateProperty
#synthesize member;
- (void) trySettingPrivateProperty {
self.member = #"A Value";
NSLog(#"myClass.member = %#", self.member);
}
#end
You can check more detail in Private properties for iPhone Objective-C
Edit:
Thanks for Abizern and Paul's comment, but in fact I got nothing compile error for this program.
I think RIP's question is "Why I set the variable in #private but I can still modify the variable like instance.variable"
The answer is although he set the variable as #private, but claim #property for variable in .h file also provide public methods getter and setter. So he can still get the instance variable use instance.variable. For OOP design pattern you should not expose your internals publicly. So if you want to use a variable privately only in its class and no one know it. And you still want to use getter and setter to access this variable in its class. you should claim #property in .m file like I did above. I claim the #property in .m file, it's a #interface extension(unnamed category). So you can make it "like" private. Because you cannot access this variable from anywhere outside this class. So it's just like a "private #property" that I mention about.
Two useful articles for you Public Properties with Private Setters and Private properties for iPhone Objective-C
We declare properties using the #property keyword and synthesize it in the implementation file. My question is,
What if I declare a property using the #property keyword and also declare a variable in the interface block with the same name? For example, consider the following code,
Interface:
#interface myClass : NSObject {
NSString *myClass_name; // LINE 1
}
#property(nonatomic, retain) NSString *myClass_name; // LINE 2
#end
Implementation:
#implementation myClass
#synthesize myClass_name // LINE 3
#end
Declaring myClass_name in LINE 1 will make any problem? Like any reference problem or any unnecessary memory consumption problem?
No, in fact, declaring properties like that expects it. You could replace your declaration to:
#interface MyClass : NSObject {
NSString *ivar;
}
#property (nonatomic, retain) NSString *myClass_name;
#end
And then change your implementation to
#implementation MyClass
#synthesize myClass_name = ivar;
#end
(If you don't specify the = some_ivar, it will assume the ivar has the same name as the property.)
You always need to have the following lines:
Declaration of the property (Line 2)
Synthesization of the property (Line 3)
When you synthesize the property, if you do not specify which ivar to use (by using =ivar at the end), it will assume that there is an ivar with the same name as the property.
Declaring properties and synthesizing it will not create any reference problem in your case.
Doing this will create accessor and setter methods for your instance variable in your class.
If the variable names in the property and the one declared in the class, then the xcode will refer both as a single variable.
Line 3 and Line 4 are must. Line 1 is optiona
I got the following content from Apple's doc for Declared Properties. I am posting it here, so that it may be helpful for someone in future.
Runtime Difference
In general the behavior of properties is identical on all runtimes (see Runtime Versions and Platforms in Objective-C Runtime Programming Guide). There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.
For #synthesize to work in the legacy runtime, you must either provide an instance variable with the same name and compatible type of the property or specify another existing instance variable in the #synthesize statement. With the modern runtime, if you do not provide an instance variable, the compiler adds one for you. For example, given the following class declaration and implementation:
#interface MyClass : NSObject {
float sameName;
float otherName;
}
#property float sameName;
#property float differentName;
#property float noDeclaredIvar;
#end
#implementation MyClass
#synthesize sameName;
#synthesize differentName=otherName;
#synthesize noDeclaredIvar;
#end
the compiler for the legacy runtime would generate an error at #synthesize noDeclaredIvar; whereas the compiler for the modern runtime would add an instance variable to represent noDeclaredIvar.
The following is the Object-oriented way:
DeclaringProperties.h
#interface DeclaringProperties : NSObject
// ivars and {} can be omitted
#property (nonatomic, readwrite, retain) NSString *normal;
#property (nonatomic, readwrite, retain) NSString *alias;
#property (nonatomic, readonly, retain) NSString *readonly;
- (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias;
#end
DeclaringProperties.m
#import "DeclaringProperties.h"
// private interface
#interface DeclaringProperties ()
#property (nonatomic, readwrite, retain) NSString *readonly; // readwrite for self
#property (nonatomic, readwrite, retain) NSString *private;
#property (nonatomic, readwrite, retain) NSString *retain;
#end
#pragma mark -
#implementation DeclaringProperties
#synthesize normal, alias = _alias, readonly, private, retain;
// You can not use "normal" here;
// But you can still use "alias", and it is highlighted in XCode!
- (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias {
self = [super init];
if (self) {
self.normal = aNormal;
self.alias = alias;
self.readonly = #"readonly";
self.private = #"private";
// allocated(copied) variable for retained(copied) property should be released or autoreleased
NSString *alloc = [[NSString alloc] init];
self.retain = alloc;
[alloc release];
// or
self.retain = [[NSString alloc] init];
[self.retain release];
// or
self.retain = [[[NSString alloc] init] autorelease];
// I don't like ;)
retain = [[NSString alloc] init];
}
return self;
}
- (void) dealloc {
self.normal = nil;
self.alias = nil;
self.readonly = nil;
self.private = nil;
self.retain = nil;
[super dealloc];
}
#end