Is it ok to have overriden getters of an Objective-C class be static? - objective-c

I have some existing code I'm modifying from another developer. They have a static NSString declared as follows...
static NSString *myStaticString;
This string should be initialized before use. What I'm looking to do is have a property method overriden which will ensure the variable is set. Here's what my suggested layout would look like...
static NSString *myStaticString;
#interface MyClass ()
#property (readonly) NSString *myProperty;
#end
#implementation MyClass
+(NSString *)myProperty
{
if (!myStaticString)
myStaticString = [#"My string value!" retain];
return myStaticString;
}
#end
The new thing for me here is I've never declared a getter as a static method and to be honest I don't know if that is a good idea or not.

In answer to the question (and I paraphrase) "is it ok to have getters return a pointer to a static?" the answer is yes, it is.
The issue here is, though, that getters are instance methods, and you've defined a class method. So you'll end up with a confusing combination of your explicitly defined class method that happens to bear the same name of an automatically synthesized getter instance method (and, worse, that synthesized getter instance method will just be returning a pointer to some automatically synthesized ivar, which is obviously not what you intended). Bottom line, you are not overriding the getter like you obviously thought you were.
As bbum pointed out, you can easily remedy this by defining this explicitly declared method as an instance method. By doing that, you will thereby be overriding the getter, accomplishing what you probably intended.
Personally, since there's nothing here that requires an instance method, I might be inclined to just retire the property altogether and have the class method return a pointer to the string referenced by your static variable. In that case, I'd suggest one of two approaches:
If the string is truly a constant, then I might do something like:
// MyClass.h
#interface MyClass : NSObject
+ (NSString *)someString;
#end
and
// MyClass.m
#import "MyClass.h"
static NSString * const kSomeInternalConstant = #"my string";
#implementation MyClass
+ (NSString *)someString
{
return kSomeInternalConstant;
}
#end
If the string is defined at runtime, but does not change while the app is running, then I'd replace the MyClass.m with:
// MyClass.m
#import "MyClass.h"
#implementation MyClass
+ (NSString *)someString
{
static NSString *someInternalString = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
someInternalString = ... // set it to be whatever you want
});
return someInternalString;
}
#end
Clearly, replace these variable names with something more logical, but hopefully this illustrates the idea.

If you're looking for the class-level equivalent of #property, then the answer is "there's no such thing". But remember, #property is only syntactic sugar, anyway; it just creates appropriately-named object methods.
You still can use class methods that access static variables which have only a slightly different syntax.
Here's thread safe example:
// Foo.h
#interface Foo {
}
+(NSDictionary*) dictionary;
// Foo.m
+(NSDictionary*) dictionary
{
static NSDictionary* fooDict = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
// create dict
});
return fooDict;
}

You need it to be an instance method:
-(NSString *)myProperty
{
if (!myStaticString)
myStaticString = [#"My string value!" retain];
return myStaticString;
}
And, yes, that is fine.
• The retain is odd; don't need it, doesn't hurt. Best turn on ARC and be done with it.
• I'd move the static into the method or, if it never changes, just return #"My string value!" directly.
• This is not an uncommon pattern; this class may return a default, static, value and subclasses might override to return a different value, as necessary.
• When initializing a static, use dispatch_once. In this case, it doesn't matter as it is an assignment of a static constant string. But, like the retain, best to follow convention (i.e. eliminate the retain, use dispatch_once or just return the value directly).

Related

Singleton property access in objective C

I'm using a standard, modern singleton class with a singleton holding a CTFontRef, like so:
#interface MySingleton : NSObject {
CTFontRef paintingFont;
}
#property (readonly) CTFontRef paintingFont;
#end
#implementation MySingleton
+ (MySingleton*)sharedInstance
{
static dispatch_once_t once;
static MySingleton *sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
//NB
sharedInstance->paintingFont =
CTFontCreateWithName(CFSTR("Helvetica"), 80.0, nil);
});
return sharedInstance;
}
#end
Then elsewhere I call [[MySingleton sharedinstance] paintingFont].
However, this call returns nil until I insert an underscore before paintingFont like so:
sharedInstance->_paintingFont =
CTFontCreateWithName(CFSTR("Helvetica"), 80.0, nil);
Why is this? Shouldn't the compiler require me to include the underscore? If not what is the purpose of the earlier version? And where did this underscore come in? I never declared the property with an underscore to begin with, I just see these seemingly random insertions of them into variable names in the debugger window.
Since Xcode 4.4, when you declare a #property, the compiler will automatically create an ivar for you and #synthesize the accessor methods. The default ivar is one with an underscore.
Using the -> syntax you access ivars directly and not the property. So, in your sharedInstance method you set your own ivar (without the underscore). However when you later try to access it, you use the [ ] which will use the automatically synthesized getter method to access your property (and the automatically generated ivar with an underscore).
You should use the . notation instead of the -> to access the property. Or simply use the automatically generated ivar called _paintingFont.
You can also make a property readwrite in your implementation file by adding the code below. This will allow you to use the dot syntax in your implementation to set the property, but still leave it readonly for other classes.
#interface MySingleton ()
#property (readwrite) CTFontRef paintingFont;
#end
If you want a different ivar, you can use #synthesize to override it. In both cases, you don't have to declare an ivar anymore.
#implementation MySingleton
#synthesize paintingFont;
....
#end
This is because in declaring a property paintingFont the Obj C compiler creates an instance variable _paintingFont.
In general the setting of a property/variable can either be done by
The instance as in your solution sharedInstance->_paintingFont = ...
Using the property and . notation sharedInstance.paintingFont = .... This calls the generated method setPaintingFont which then assigns to the instance variable.
However in this case the property is readonly so method 2 cannot be used.

Is it possible to override property's method?

I need to add some codes when MyClass's string value is changed.
So I'm trying to override a MyClass's string property method.
But I have no idea.. so I do like following.
Is it correct?
How to override property's method?
#interface MyClass{
NSString *string;
}
#property(retain, nonatomic) NSString *string;
#end
#implementation MyClass
- (void)setString:(NSString*)newString{
// want to add some codes.
[self setString:newString]; <= Is this correct?
}
#end
- (void)setString:(NSString*)newString{
// want to add some codes.
string = newString; //This is the setter method!
// You will need to consider memory management etc.
}
What you are probably more up to is this:
- (void)setString:(NSString*)newString{
// want to add some codes.
[super setString:newString];
}
[self setString:newString] at this place would be a an endless recursive loop. [super setString:newString] should call the superlass' setter. However, I never did that myself.
What you are trying to do is not to override (no subclass are involve in your code snippet).
What is in your code is just the declaration #interface and the definition #implementation. It have the same meaning and utility to the declaration/definition in C where you put declaration in a .h file and definition in a .c file.
Assuming that your are speaking of how to synthesize, your code is almost correct. You are just missing the getter - (NSString *) string; or you what it readonly.
As for how to do correctly the assignment you should use the =
- (void)setString:(NSString*)newString{
// want to add some codes.
string = newString; // Correct way of doing it
}
There is 2 way to synthesize a propertie, either by defining the setter and getter by hand or either by using the syntactic sugar #synthesize.
For a better understanding consider that #property and #synthesize are both syntactic sugar. (Only that #property is adding some semantic with the retain, strong, etc.. keyword).
Better is to read the documentation that you can found. There is many easy to found web page where you could have more details.

Is this a new way to define private instance variables in Objective-C?

I've recently updated to Xcode 4.3.2 and found that I can now declare private instance variables inside #implementation block like so:
#interface TestClass : NSObject
#property (nonatomic, copy) NSString *testProp;
#end
#implementation TestClass {
NSString *_testPropStore;
}
- (NSString *)testProp { return _testPropStore; }
- (void)setTestProp:(NSString *)testProp { _testPropStore = [testProp copy]; }
- (id)init {
if (self = [super init]) {
_testPropStore = nil;
}
return self;
}
#end
Notice the NSString *_testPropStore line inside #implementation brace block.
I've also tested with the following code:
TestClass *c1 = [[TestClass alloc] init];
TestClass *c2 = [[TestClass alloc] init];
c1.testProp = #"Hello";
c2.testProp = #"World";
NSAssert(c1.testProp == c2.testProp, #"It's working!");
Which seems to work fine. (That is, the app crashes with the "It's working" message at the NSAssert line.)
So is this a new feature of Objective-C for declaring private instance variables? Since I discovered this by accident, I would love to know if it is just for declaring private instance variables or will there be any side effects that I'm not aware of?
I couldn't find any relevant document since most questions of such type with the word private just ended up with answers on how to declare them on a private extension category which is different.
It's for real, it's the new way,* it's great, and, yes, it's in the docs. The Objective-C Programming Language, which is as close as we get to having an actual spec for the language, has the following to say:
The definition of a class is structured very much like its declaration. It begins with an #implementation directive and ends with the #end directive. In addition, the class may declare instance variables in braces after the #implementation directive:
#implementation ClassName
{
// Instance variable declarations.
}
// Method definitions.
#end
There's also a historical note a little ways back from that link, addressing the fact that we used to have to declare ivars in the interface block:
Historically, the interface required declarations of a class’s instance variables, the data structures that are part of each instance of the class. ... Instance variables represent an implementation detail, and should typically not be accessed outside of the class itself. Moreover, you can declare them in the implementation block or synthesize them using declared properties. Typically you should not, therefore, declare instance variables in the public interface and so you should omit the braces.
For the question of privacy, yes, these variables are truly private -- they act like ivars declared in the interface with the #private directive. This means that subclasses can't access them, by default. Their visibility can be changed, however, using either #protected or (if necessary for some bizarre reason) #public:
#interface Stuper : NSObject
#end
#implementation Stuper
{
#protected
NSString * sangfroid;
}
#end
#interface Stub : Stuper
- (void)setSangfroid: (NSString *)newSangfroid;
#end
#implementation Stub
- (void)setSangfroid: (NSString *)newSangfroid {
sangfroid = [newSangfroid copy];
}
*You have to use clang > 3.0, I believe, so that's just a few months ago as of this posting. GCC won't do it.
It's pretty new and it's valid as long as any compiler you need supports it.
It's great for minimizing your dependencies -- the includes and forwards may largely be in the implementation file. For this reason, and if all the compilers you use support it, then it's a better place for your ivars than in the #interface block.
A final caveat is that our current (may.2.2012) debuggers do not support this.

Objective-C Static Class Level variables

I have a class Film, each of which stores a unique ID. In C#, Java etc I can define a static int currentID and each time i set the ID i can increase the currentID and the change occurs at the class level not object level. Can this be done in Objective-C? I've found it very hard to find an answer for this.
Issue Description:
You want your ClassA to have a ClassB class variable.
You are using Objective-C as programming language.
Objective-C does not support class variables as C++ does.
One Alternative:
Simulate a class variable behavior using Objective-C features
Declare/Define an static variable within the classA.m so it will be only accessible for the classA methods (and everything you put inside classA.m).
Overwrite the NSObject initialize class method to initialize just once the static variable with an instance of ClassB.
You will be wondering, why should I overwrite the NSObject initialize method. Apple documentation about this method has the answer: "The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.)".
Feel free to use the static variable within any ClassA class/instance method.
Code sample:
file: classA.m
static ClassB *classVariableName = nil;
#implementation ClassA
...
+(void) initialize
{
if (! classVariableName)
classVariableName = [[ClassB alloc] init];
}
+(void) classMethodName
{
[classVariableName doSomething];
}
-(void) instanceMethodName
{
[classVariableName doSomething];
}
...
#end
References:
Class variables explained comparing Objective-C and C++ approaches
As of Xcode 8, you can define class properties in Obj-C. This has been added to interoperate with Swift's static properties.
Objective-C now supports class properties, which interoperate with Swift type properties. They are declared as: #property (class) NSString *someStringProperty;. They are never synthesized. (23891898)
Here is an example
#interface YourClass : NSObject
#property (class, nonatomic, assign) NSInteger currentId;
#end
#implementation YourClass
static NSInteger _currentId = 0;
+ (NSInteger)currentId {
return _currentId;
}
+ (void)setCurrentId:(NSInteger)newValue {
_currentId = newValue;
}
#end
Then you can access it like this:
YourClass.currentId = 1;
val = YourClass.currentId;
Here is a very interesting explanatory post I used as a reference to edit this old answer.
2011 Answer: (don't use this, it's terrible)
If you really really don't want to declare a global variable, there another option, maybe not very orthodox :-), but works... You can declare a "get&set" method like this, with an static variable inside:
+ (NSString*)testHolder:(NSString*)_test {
static NSString *test;
if(_test != nil) {
if(test != nil)
[test release];
test = [_test retain];
}
// if(test == nil)
// test = #"Initialize the var here if you need to";
return test;
}
So, if you need to get the value, just call:
NSString *testVal = [MyClass testHolder:nil]
And then, when you want to set it:
[MyClass testHolder:testVal]
In the case you want to be able to set this pseudo-static-var to nil, you can declare testHolder as this:
+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test {
static NSString *test;
if(shouldSet) {
if(test != nil)
[test release];
test = [_test retain];
}
return test;
}
And two handy methods:
+ (NSString*)test {
return [MyClass testHolderSet:NO newValue:nil];
}
+ (void)setTest:(NSString*)_test {
[MyClass testHolderSet:YES newValue:_test];
}
Hope it helps! Good luck.
On your .m file, you can declare a variable as static:
static ClassName *variableName = nil;
Then you can initialize it on your +(void)initialize method.
Please note that this is a plain C static variable and is not static in the sense Java or C# consider it, but will yield similar results.
In your .m file, declare a file global variable:
static int currentID = 1;
then in your init routine, refernce that:
- (id) init
{
self = [super init];
if (self != nil) {
_myID = currentID++; // not thread safe
}
return self;
}
or if it needs to change at some other time (eg in your openConnection method), then increment it there. Remember it is not thread safe as is, you'll need to do syncronization (or better yet, use an atomic add) if there may be any threading issues.
As pgb said, there are no "class variables," only "instance variables." The objective-c way of doing class variables is a static global variable inside the .m file of the class. The "static" ensures that the variable can not be used outside of that file (i.e. it can't be extern).
Here would be an option:
+(int)getId{
static int id;
//Do anything you need to update the ID here
return id;
}
Note that this method will be the only method to access id, so you will have to update it somehow in this code.
(Strictly speaking not an answer to the question, but in my experience likely to be useful when looking for class variables)
A class method can often play many of the roles a class variable would in other languages (e.g. changed configuration during tests):
#interface MyCls: NSObject
+ (NSString*)theNameThing;
- (void)doTheThing;
#end
#implementation
+ (NSString*)theNameThing { return #"Something general"; }
- (void)doTheThing {
[SomeResource changeSomething:[self.class theNameThing]];
}
#end
#interface MySpecialCase: MyCls
#end
#implementation
+ (NSString*)theNameThing { return #"Something specific"; }
#end
Now, an object of class MyCls calls Resource:changeSomething: with the string #"Something general" upon a call to doTheThing:, but an object derived from MySpecialCase with the string #"Something specific".
u can rename the class as classA.mm and add C++ features in it.
Another possibility would be to have a little NSNumber subclass singleton.

Is there a difference between an "instance variable" and a "property" in Objective-c?

Is there a difference between an "instance variable" and a "property" in Objective-c?
I'm not very sure about this. I think that an "property" is an instance variable that has accessor methods, but I might think wrong.
A property is a more abstract concept. An instance variable is literally just a storage slot, like a slot in a struct. Normally other objects are never supposed to access them directly. A property, on the other hand, is an attribute of your object that can be accessed (it sounds vague and it's supposed to). Usually a property will return or set an instance variable, but it could use data from several or none at all. For example:
#interface Person : NSObject {
NSString *name;
}
#property(copy) NSString *name;
#property(copy) NSString *firstName;
#property(copy) NSString *lastName;
#end
#implementation Person
#synthesize name;
- (NSString *)firstName {
[[name componentsSeparatedByString:#" "] objectAtIndex:0];
}
- (NSString *)lastName {
[[name componentsSeparatedByString:#" "] lastObject];
}
- (NSString *)setFirstName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:#" "];
NSArray *newNameArray [[NSArray arrayWithObjects:newName, nil] arrayByAddingObjectsFromArray:[nameArray subarrayWithRange:NSMakeRange(1, [nameArray size]-1)]];
self.name = [newNameArray componentsJoinedByString:#" "];
}
- (NSString *)setLastName:(NSString *)newName {
NSArray *nameArray = [name componentsSeparatedByString:#" "];
NSArray *newNameArray [[nameArray subarrayWithRange:NSMakeRange(0, [nameArray size]-2)] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:newName, nil]];
self.name = [newNameArray componentsJoinedByString:#" "];
}
#end
(Note: The above code is buggy in that it assumes the name already exists and has at least two components (e.g. "Bill Gates" rather than just "Gates"). I felt that fixing those assumptions would make the actual point of the code less clear, so I'm just pointing it out here so nobody innocently repeats those mistakes.)
A property is a friendly way of implementing a getter/setter for some value, with additional useful features and syntax. A property can be backed by an instance variable, but you can also define the getter/setter to do something a bit more dynamic, e.g. you might define a lowerCase property on a string which dynamically creates the result rather than returning the value of some member variable.
Here's an example:
// === In your .h ===
#interface MyObject {
NSString *propertyName;
}
// ...
#property (nonatomic, retain) NSString *propertyName;
// === In your .m #implementation ===
#synthesize propertyName /* = otherVarName */;
The #property line defines a property called propertyName of type NSString *. This can be get/set using the following syntax:
myObject.propertyName = #"Hello World!";
NSLog("Value: %#", myObject.propertyName);
When you assign to or read from myObject.propertyName you are really calling setter/getter methods on the object.
The #synthesize line tells the compiler to generate these getter/setters for you, using the member variable with the same name of the property to store the value (or otherVarName if you use the syntax in comments).
Along with #synthesize you can still override one of the getter/setters by defining your own. The naming convention for these methods is setPropertyName: for the setter and propertyName (or getPropertyName, not standard) for the getter. The other will still be generated for you.
In your #property line you can define a number of attributes in parens for the property that can automate things like thread-safety and memory management. By default a property is atomic meaning the compiler will wrap #synthesized get/set calls with appropriate locks to prevent concurrency issues. You can specify the nonatomic attribute to disable this (for example on the iPhone you want to default most properties to nonatomic).
There are 3 attribute values that control memory management for any #synthesized setters. The first is retain which will automatically send release to old values of the property, and retain to the new values. This is very useful.
The second is copy which will make a copy of any values passed in rather than retaining them. It is good practice to use copy for NSString because a caller could pass in an NSMutableString and change it out from under you. copy will make a new copy of the input which only you have access to.
The third is assign which does a straight pointer assign without calling retain/release on the old or new object.
Lastly you can also use the readonly attribute to disable the setter for the property.
I use properties for the interface part - where the object interfaces with other objects
and instance variables are stuff that you need inside your class - nobody but you is supposed to see and manipulate those.
By default, a readwrite property will be backed by an instance variable, which will again be synthesized automatically by the compiler.
An instance variable is a variable that exists and holds its value for the life of the object. The memory used for instance variables is allocated when the object is first created (through alloc), and freed when the object is deallocated.
Unless you specify otherwise, the synthesized instance variable has the same name as the property, but with an underscore prefix. For a property called firstName, for example, the synthesized instance variable will be called _firstName.
Previously people use properties publicly and ivars for private usage, but since several years ago, you can also define properties in #implementation to use them privately. But I'd still use ivars when possible, since there are less letters to type, and it runs faster according to this article. It makes sense since properties are mean to be "heavy": they are supposed to be accessed from either generated getters/setters or the ones manually written.
However, in recent codes from Apple, ivars are not used anymore. I guess because it's more like objc rather than C/C++, plus it's easier to use properties with assign, nullable, etc.
Objective-C Property vs Instance variable (iVar)
[Swift variable, property...]
Instance variable
#interface SomeClass: NSObject
NSString *someVariable;
#end
Property
#interface SomeClass: NSObject
#property (nonatomic, strong) NSString *someVariable;
#end
Property uses Instance variable inside. property = variable + bounded getter/setter. It is a method call with variable syntax and access
#property generates getter and setter methods(accessor methods) which uses backing ivar(aka backing field) which you can use via underscore _<var_name> (_someVariable).
Since it calls a method - method dispatch mechanism is used that is why KVO[About] can be applied
When you override accessor methods backing iVar is not generated that is why you can declare a new property explicitly or use #synthesize[About] to generate a new one or link with existing
#import "SomeClass.h"
#interface SomeClass()
#property (nonatomic, strong) NSString *someVariable;
#end
#implementation SomeClass
- (void) foo {
//property getter method
NSString *a1 = self.someVariable; //NSString *a1 = [self someVariable];
//property setter method
self.someVariable = #"set someVariable"; //[self setSomeVariable:#"set someVariable"];
//iVar read
NSString *a2 = _someVariable;
//iVar write
_someVariable = #"set iVar";
}
//if you overriding someVariable getter and setter the iVar(_someVariable) is not generated, that is why you can:
//1. create some variable explicitly
NSString *_someVariable;
//or
//2. use #synthesize
#synthesize someVariable = _someVariable;
//overriding
- (NSString*) someVariable {
return _someVariable;
}
- (void)setSomeVariable: (NSString*) updatedSomeVariable {
_someVariable = updatedSomeVariable;
}
#end
[property attributes]