Declare a static property in an Objective-C class interface - objective-c

I'm defining an Objective-C class:
#interface MyRequest : NSObject
#property (strong, nonatomic, readonly) NSDecimalNumber *myNumber;
#property (strong, nonatomic, readonly) CommConfig *commConfig;
#property (nonatomic, assign, readonly) BOOL debug;
How do I make commConfig a static variable? When I use the 'class' keyword, the compiler gives me the following warning:
Class property 'commConfig' requires method 'commConfig' to be defined - use #dynamic or provide a method implementation in this class implementation
And the constructor doesn't recognize this line anymore:
_commConfig = commConfig

If not implemented by the programmer instance properties are automatically implemented by the compiler - an instance variable allocated and getter and/or setter methods written. Class properties are never automatically implemented, you therefore need to declare the static backing variable and define the getter. In your #implementation add:
static CommConfig *_commConfig;
+ (CommConfig *) commConfig { return _commConfig; }
You can call the backing anything you wish, e.g. to follow a naming convention for global/static variables.
HTH

Related

Objective C: Should I assign the variable AND create a property or is just one of them enough?

I have got a header file (.h) and I want to declare name but all these ways work the same I think because I haven't seen any difference with functionality. Could you tell me what the difference is between:
This with both declarations:
#interface someClass : UIViewController
{
NSString *name;
}
#property (nonatomic, copy) NSString *name;
#end
Without variable:
#interface someClass : UIViewController
{
}
#property (nonatomic, copy) NSString *name;
#end
Or Without property:
#interface someClass : UIViewController
{
NSString *name;
}
#end
#interface someClass : UIViewController
{
NSString *name;
}
#property (nonatomic, copy) NSString *name;
#end
Doing this you will explicitly declare both a property and an ivar.
A property is just a set of methods:
- (void)setName:(NSString*)name;
- (NSString*)name;
An ivar is the memory store holding the value that the property methods manage. This allows you to do:
self.name = ... // access through setter method
name = ... // direct access
The advantage of using properties is that they deal with memory management for you. E.g., in your case, the property is of type copy: this means that with the first syntax (self.name = ...) a copy of the object will be done. If not using properties, you would explicitly need to do: name = [originalString copy]; to obtain the same effect.
Other options you can specify for properties (but not ivars) are: strong and weak ownerships.
Furthermore, a property also represents a public interface to access the variable from outside your class.
Using direct access you are on your own as to memory management (if you are not using ARC).
If you are using ARC and don't define properties, you will not be able to control how the memory is managed by specifying the ownership: strong, weak, retain).
#interface someClass : UIViewController
{
}
#property (nonatomic, copy) NSString *name;
#end
Here you only declare the properties; the ivar is "inferred" by the #synthesize directive in your implementation file. This is only possible in Objective C 2.0 and later (previously, the ivar declaration as above was mandatory).
The same considerations as above applies, with a minor nuance: with older versions of LLVM (ObjC compiler) you will not be able to reference directly the auto-synthesized ivar; with current version of LLVM, if you omit the #synthesize directive, then an automatic ivar named after your property would also be declared (in your case it would be _name).
This last paragraph may seem a bit "advanced", or contrived, but you can safely ignore it.
#interface someClass : UIViewController
{
NSString *name;
}
#end
In this case you are only declaring the ivar. No accessor methods. You will need to handle memory management on your own (if not using ARC), futhermore you will not be able to access the variable from outside the class. For that you need accessors.
Hope this helps.
Case 1:
The is the old method, here the #property and variable are not related until you #synthesize name = name;
Access methods :
variable : name = #"hello"; //direct access to viariable
setter/getter : self.name = #"hello" // set value to name using setName: selector
With the latest xcode just the property is enough.
Case 2:
the new xcode style. Here the synthesize and variable creation is taken care by the compiler. (so less 2 lines of code and this also helps with memory management)
Access methods :
variable : _name = #"hello"; //direct access to viariable
setter/getter : self.name = #"hello" // set value to name using setName: selector
Case 3:
Here the name is just a variable and it dose not have a setter or a getter.
with out property (or) setter & getter this is as good as a local variable and it cannot be accessed from other objects.

Difference between #property (nonatomic, readonly) and #property inside class extension?

I have an Objective-c class "MyClass". In MyClass.m I have a class extension that declares a CGFloat property:
#interface MyClass ()
#property (nonatomic) CGFloat myFloat;
#end
#implementation MyClass
#synthesize myFloat;
//...
#end
What changes (if anything) when the property is declared using the readonly keyword?
#interface MyClass ()
#property (nonatomic, readonly) CGFloat myFloat;
#end
#implementation MyClass
#synthesize myFloat;
//...
#end
Perhaps in the first case I can say self.myFloat = 123.0; and CGFloat f = self.myFloat; inside MyClass? Then in the second case the readonly keyword prevents the assignment self.myFloat = 123.0; but allows the read CGFloat f = self.myFloat;
The option readonly means that only the getter method is being declared for this property. Thus, without a setter, it can't be modified via myObject.myFloat=0.5f;
If you don't declare it readonly, it's read write by default.
Declaring your property via () extension does not modify the access mode but it modifies the scope; it will be a "private" property.
#synthesize uses the #property definition to generate the appropiate getter/setter for the iVar. When you specify readonly, no setter is generated. This is not strictly enforced as you can write your own setter if you choose (though that doesn't make a ton of sense).
Declaring the property in a category simply defines the scope of the property to be within that category.
You're right, declaring your property as readonly you tell compiler to not generate setter method automatically and so self.myFloat = 123.0; will be illegal (unless you create that method manually).

private property in Objective C

Is there a way to declare a private property in Objective C? The goal is to benefit from synthesized getters and setters implementing a certain memory management scheme, yet not exposed to public.
An attempt to declare a property within a category leads to an error:
#interface MyClass : NSObject {
NSArray *_someArray;
}
...
#end
#interface MyClass (private)
#property (nonatomic, retain) NSArray *someArray;
#end
#implementation MyClass (private)
#synthesize someArray = _someArray;
// ^^^ error here: #synthesize not allowed in a category's implementation
#end
#implementation MyClass
...
#end
I implement my private properties like this.
MyClass.m
#interface MyClass ()
#property (nonatomic, retain) NSArray *someArray;
#end
#implementation MyClass
#synthesize someArray;
...
That's all you need.
A. If you want a completely private variable. Don't give it a property.
B. If you want a readonly variable that is accessible external from the encapsulation of the class, use a combination of the global variable and the property:
//Header
#interface Class{
NSObject *_aProperty
}
#property (nonatomic, readonly) NSObject *aProperty;
// In the implementation
#synthesize aProperty = _aProperty; //Naming convention prefix _ supported 2012 by Apple.
Using the readonly modifier we can now access the property anywhere externally.
Class *c = [[Class alloc]init];
NSObject *obj = c.aProperty; //Readonly
But internally we cannot set aProperty inside the Class:
// In the implementation
self.aProperty = [[NSObject alloc]init]; //Gives Compiler warning. Cannot write to property because of readonly modifier.
//Solution:
_aProperty = [[NSObject alloc]init]; //Bypass property and access the global variable directly
It depends what you mean by "private".
If you just mean "not publicly documented", you can easily enough use a class extension in a private header or in the .m file.
If you mean "others are not able to call it at all", you're out of luck. Anyone can call the method if they know its name, even if it is not publicly documented.
As others have indicated, (currently) there is no way to truly declare a private property in Objetive-C.
One of the things you can do to try and "protect" the properties somehow is to have a base class with the property declared as readonly and in your subclasses you can redeclare the same property as readwrite.
Apple's documentation on redeclared properties can be found here: http://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW19

Initializing a readonly property

I was trying to create a property which is readonly. I wanted to initialize with a value from the class creating an instance of this class, e.g.
#property (retain,readonly) NSString *firstName;
And I tried to initialize it like this:
-(id)initWithName:(NSString *)n{
self.firstName = n;
}
Once I did this, the compiler reported an error that the readonly property cannot be assigned. So how can i do this ?
Either assign to the instance variable directly (don't forget to add a retain or copy if you need it) or redeclare the property in a private class extension. Like this:
In your .h file:
#property (readonly, copy) NSString *firstName;
In your .m file:
#interface MyClass ()
// Redeclare property as readwrite
#property (readwrite, copy) NSString *firstName;
#end
#implementation MyClass
#synthesize firstName;
...
Now you can use the synthesized setter in your implementation but the class interface still shows the property as readonly. Note that other classes that import your .h file can still call -[MyClass setFirstName:] but they won't know that it exists and will get a compiler warning.
Don't use the synthesized setter:
firstName = [n retain]; //Or copy
It is generally advised to bypass the setters in any init and dealloc methods anyway.
You can directly access the property with:
_firstName = n;
The setter method that self.firstName = n implies will not be synthesized because you specified readonly in #property (retain,readonly) NSString *firstName;, hence the compiler error.

Should I always use accessors for instance variables in Objective-C?

If I have a class with some IBOutlets, it seems kind of silly to create accessors for these.
But then I feel like I'm breaking OO practices by not always going through the accessors for instance variables.
I also feel the same way about some instance variables that should not be public, I'd rather not expose the inner workings of some classes. I can make the actual ivars private but the #property shorthand doesn't seem to be able to specify visibility. This leads me to not create accessors and just access the ivars directly. I'm not sure if this is frowned upon though. Is it?
What's the community's thoughts on this admittedly newbie question? (Please ignore dot syntax)
I'm not sure about accessing instance variables directly, I think one shouldn't, but for some variables it just doesn't make sense to use accessors. Like for the IBOutlets you mentioned.
I can only help you out with private accessors. Starting with Objective-C 2.0 you can declare extensions.
Class extensions are like “anonymous”
categories, except that the methods
they declare must be implemented in
the main #implementation block for the
corresponding class.
Just put this extension into a separate header file and you'll have private accessors that aren't visible in the header.
Public/Private
You can declare your iVars as in the #interface file to be readonly, but then re-declare them in a category so that your class can change them. Here's a quick intro to Categories.
An example:
//MyClass.h
#interface MyClass : NSObject {
NSString *name;
}
#property (readonly) NSString *name;
#end
And in the implementation file you can redeclare this:
//MyClass.m
#interface MyClass () //declare the class extension
#property (readwrite, copy) NSString *name; //redeclare the property
#end
#implementation MyClass
#synthesize name;
#end
Now, the name property is readonly external to the class, but can be changed by the class through property syntax or setter/getter syntax.
Really private iVars
If you want to keep iVars really private and only access them directly without going through #property syntax you can declare them with the #private keyword. But then you say "Ah, but they can always get the value outside the class using KVC methods such as setValueForKey:" In which case take a look at the NSKeyValueCoding protocol class method + (BOOL)accessInstanceVariablesDirectly which stops this.
IBOutlets as properties
The recommended way is to use #property and #synthesize. For Mac OS X, you can just declare them as readonly properties. For example:
//MyClass.h
#interface MyClass : NSObject {
NSView *myView;
}
#property (readonly) IBOutlet NSView *myView;
#end
//MyClass.m
#implementation MyClass
#synthesize myView;
#end