Will declaring a property in an ObjC category override a property of the same name that's declared on the public interface? - objective-c

This is not intended to solve any particular problem, just looking to understand the nuances of properties in Objc.
say I have a class Dude
# Dude.h
#interface Dude: NSObject
#property (readonly, nonatomic) NSNumber *height;
#end
I extend the class in the implementation file but change the attributes.
# Dude.m
#interface Dude()
#property (readwrite, atomic) NSNumber *height;
#end
#implementation Dude
#end
I get an error.
'atomic' attribute on property 'height' does not match the property
inherited from 'Dude'
So what is actually going on here. Is the property on the extension the same property? Am I just overriding the accessors?
Also when I change the order so that the public interface is readwrite but the private interface is readonly I get the error:
Illegal redeclaration of property in class extension 'Dude' (attribute
must be 'readwrite', while its primary must be 'readonly')
This makes me think it's an entire redeclaration but now I am less sure about what is actually happening. Looking for clarification.

You can think of this more like a public and private interface.
The interface declared in the .h file is the public interface for your class.
So if you have a reason to declare a property readonly it makes sense there.
The nameless category (Dude()) in your .m file is your private sight on the properties. So you can specify readwrite here to make your class able to change the property internally but not to the outside world.
You can also use these declaration for your methods to declare a public interface in .h and private methods in interface Dude() in .m.
The combination in your public and private interface must make sense, you can't declare a public property readwrite and say internally it is just readonly ...
And finally this is Objective-C: this is just for your editor and compiler. Everything that exists can be accessed even if it is declared some kind of private.

In Apple’s The Objective-C Programming Language, they describe “extensions” as follows, using the redeclaration of a property as an example:
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. Using the Clang/LLVM 2.0 compiler, you can also declare properties and instance variables in a class extension.
A common use for class extensions is to redeclare property that is publicly declared as read-only privately as readwrite:
#interface MyClass : NSObject
#property (retain, readonly) float value;
#end
// Private extension, typically hidden in the main implementation file.
#interface MyClass ()
#property (retain, readwrite) float value;
#end
...
So, as illustrated here, this pattern is to “redeclare” a property. It’s the same property, though. You only redeclare a property when you want the compiler to synthesize a private setter even though the public interface is declared as readonly. If you don’t redeclare the property as readwrite in the extension, a setter will not be synthesized at all.
Your various warnings actually illustrate the fact that we’re dealing with the same property, because are merely examples where the nature of your redeclaration isn’t compatible with what was included in the public interface.

Related

Controlling access to instance variables in Objective-C

From all code I've seen, almost always is used something like this for property scope definition:
Class extension
/*We declare the class extension*/
#interface MyClass ()
#property (nonatomic, retain) Type *aPrivateProperty;
- (void)aPrivateMethod;
#end
/*
We can use the main implementation block to implement our properties
and methods declared in the class extension.
*/
#implementation MyClass
/*Therefore we can use synthesize ;-)*/
#synthesize aPrivateProperty;
- (void)aPrivateMethod {
//Some code there
}
#end
But this is (from what I've seen) rarely used:
#interface MyClass : NSObject {
iVar *aProtectedIVar;
#public
iVar *aPublicIVar;
iVar *aSecondPublicIVar;
#protected
iVar *aSecondProtectedIVar;
#private
iVar *aPrivateIVAr;
}
#end
Why modifiers like #private, #protected and #public are not used so much in Objective-C if they are available?
Access modifiers for instance variables are rarely used because they expose more information about the structure of your object than you may wish to allow others to see. An exposure of a public variable is binding on all future implementations to have the same variable. Property, on the other hand, hides the variable, letting you change your mind later on, and compute result instead of storing it.
Property access is highly optimized in Objective-C, so there is virtually no run-time hit for exposing a property instead of a variable. Since you gain flexibility for free by switching to property, exposing variables with #public is rarely used.
I was interested why class extension, (like from example above) is used more often than #private modifier
Because class extension lets you place private properties with your .m file, rather than your .h header file. Headers included from other .m files create compile-time dependencies, which are easily avoided by placing implementation details into class extensions.
You can declare a global variable in three places.
If you declare this in .h is public:
#property (nonatomic, strong) NSString *publicString;
Instead if you declare the same in .m is private there are no need for the second way.

private fields on Objective C

What is difference of these three cases (all of them are used like private fields):
1.
#interface APLParseOperation : NSOperation
#property (copy, readonly) NSData *earthquakeData;
#end
2.
#interface APLParseOperation () <NSXMLParserDelegate>
#property (nonatomic) APLEarthquake *currentEarthquakeObject;
#property (nonatomic) NSMutableArray *currentParseBatch;
#property (nonatomic) NSMutableString *currentParsedCharacterData;
#end
3.
#implementation APLParseOperation
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
It's a good practice or smthing else?
I'm going to go through each example you gave, and describe them. I was just having trouble with this yesterday so I feel your pain.
1.
#interface APLParseOperation : NSOperation
#property (copy, readonly) NSData *earthquakeData;
#end
By using the #property keyword, the compiler automatically synthesizes your accessor methods for you, and also a backing instance variable. However, because you are using the readonly property attribute, the compiler is only synthesizing a getter method for you.
2.
#interface APLParseOperation () <NSXMLParserDelegate>
#property (nonatomic) APLEarthquake *currentEarthquakeObject;
#property (nonatomic) NSMutableArray *currentParseBatch;
#property (nonatomic) NSMutableString *currentParsedCharacterData;
#end
This second example is very similar to the first. However, because none of them have the readonly property attribute, they will all have getters and setter methods synthesized for them, as well as the backing instance variable.
3.
#implementation APLParseOperation
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
For this last example, you are just declaring instance variables. These are also private to your implementation file, where as the other 2 examples had declarations being made in your classes interface file.
No setter or getter methods are being synthesized for you by the compiler. You are simply declaring some instance variables.
In terms of private and public, your first and second examples both provide declarations that will be visible to other classes, as long as they import the current class's header file. The first example however, only provides a way to "get" the property and read it, there is no setter method because you used the readonly property attribute. With the second example, outside classes will be able to access your getter and setter methods for your property, so they can read and write.
For the third example, these are just instance variables and they are private to your class's implementation file. Basically, no outside classes will even know that they exist.
This is not private. It is still readable by outside classes, though it can't be written.
Private properties. It can be useful if you want to write custom getters and setters. If you are not using ARC, it can be helpful for memory management.
Private members. This is my favorite. It's easy to read and easy to write.
defines a public property visible to all users of the APLParseOperation class.
defines properties through an extension, making them available only to the implementation methods.
defines instance variables which are implicitly private.
Number 1 is used when you want to make your properties public. Numbers 2 and 3 are for private properties and instance variables. You can also declare instance variables in class extensions, like this:
#interface APLParseOperation () <NSXMLParserDelegate>
{
NSDateFormatter *_dateFormatter;
BOOL _accumulatingParsedCharacterData;
BOOL _didAbortParsing;
NSUInteger _parsedEarthquakesCounter;
}
#end
There is not much difference between that and the number 3. It is a good idea to pick one style, and stick to it in all your code.
Case 1. is not private. It's a public read-only property: Reading is public, writing is only possible only in the private scope via the underlying ivar (thanks for pointing it out #mah).
Case 2. (if in a .m file) is extending the class by adding 3 private properties and making the protocol conformance private too.
Case 3. is declaring 4 private instance variables that can be used in all the implementation scope.
Objective-C best practice for private properties is case 2., as case 1. is not private at all, just read-only, and case 3. uses instance variables (aka ivar) which is less conventional than properties. More on that here: Reason to use ivars vs properties in objective c
Hope this helps,

Why does the compiler warn when redeclaring base class's readwrite property as readonly in subclass?

The Apple doc quoted later seems to indicate this is permissible, though I'll admit never having a reason to do it in a subclass until now.
I have a base class with a public readwrite property and a subclass where I redeclare the property as readonly. The subclass also has a class extension which again redeclares the property as readwrite to achieve the common "public readonly, private readwrite" Objective-C pattern. However, I get the following compiler warning:
warning: Semantic Issue: Attribute 'readonly' of property 'foo' restricts attribute 'readwrite' of property inherited from 'Base'
I'm using Xcode 4.1 build 4B110 with LLVM 2.1 (though LLVM GCC4.2 and GCC4.2 give the same warning) on 10.7.
Here's a stripped-down example which exhibits the compiler warning:
#import <Foundation/Foundation.h>
#interface Base : NSObject
#property (nonatomic, readwrite) BOOL foo;
#end
#implementation Base
#dynamic foo;
#end
// Subclass
#interface Sub : Base
#property (nonatomic, readonly) BOOL foo;
#end
// Class extension
#interface Sub ()
#property (nonatomic, readwrite) BOOL foo;
#end
#implementation Sub
#dynamic foo; // it warns with #synthesize as well
#end
Here's a relevant passage from Apple's The Objective-C Programming Language:
Property Redeclaration
You can redeclare a property in a subclass, but (with the exception of
readonly versus readwrite) you must repeat its attributes in whole in
the subclasses. The same holds true for a property declared in a
category or protocol—while the property may be redeclared in a category
or protocol, the property’s attributes must be repeated in whole.
If you declare a property in one class as readonly, you can redeclare it
as readwrite in a class extension (see “Extensions”), in a protocol, or
in a subclass (see “Subclassing with Properties”). In the case of a class
extension redeclaration, the fact that the property was redeclared prior
to any #synthesize statement causes the setter to be synthesized. The
ability to redeclare a read-only property as read/write enables two
common implementation patterns: a mutable subclass of an immutable class
(NSString, NSArray, and NSDictionary are all examples) and a property that
has a public API that is readonly but a private readwrite implementation
internal to the class. The following example shows using a class extension
to provide a property that is declared as read-only in the public header
but is redeclared privately as read/write.
I redeclare public readonly properties readwrite in class extensions all the time, but I guess I've never had cause to do it an a subclass. However, unless I'm reading it wrong, the paragraphs above seem to indicate that it's kosher. Can anyone set me straight and/or reconcile the apparent conflict between the docs and the compiler?
Why do I want to do this? My real-world situation is more complex, of course. I can make design changes to work around this if needed, but this seemed like the least-friction alternative (the need to do this at all is being driven by other changes).
It says you can redeclare a readonly property as readwrite but you're doing the opposite. You can't/shouldn't do it because it's possible to do this:
Sub* s = [[[Sub alloc] init] autorelease];
Base* b = s;
b.foo = YES; //legal for `Base` objects, but not legal for `Sub` objects
It's a violation of the the Liskov Substitution Priciple.

Is declare new property in class extension a bad practice in Objective-C?

One strong advantage of class extension is that with class extension you can declare a readonly property in the header file and override this property in class extension as readwrite property. Like below :
//SomeClass.h
#interface SomeClass : NSObject
{
NSInteger someInt; //with modern runtime you can omit this line
}
#property (readonly) NSInteger someInt;
#end
//SomeClass.m
#interface SomeClass ()
#property (readwrite) NSInteger someInt;
#end
#implementation SomeClass
#synthesize someInt;
#end
But if you use a modern runtime ,you can also declare a totally new property in the class extension (which also generate an iVar for that property if there isn't).
//SomeClass.h
#interface SomeClass : NSObject
{
}
#end
//SomeClass.m
#interface SomeClass ()
#property (readwrite) NSInteger someInt;
#end
#implementation SomeClass
#synthesize someInt;
#end
Here's my question : I think declare a totally new property in class extention is somehow has some side effects. Because class extension my not be in the header file and someone else who subclass the class may not know about that "secret property". And if he declare a property with the same name of that "secret property". And this new property's getter and setter method will override the super class's. Isn't this a problem?And why would modern runtime allow such thing happen?
EDIT I posted another question about this topic , please check it out:
The risk of declare new propery in class extension (Ojbective-C) , how to solve it?
I don't think it's bad practice to declare a new property in a class extension. I do this with some frequency. The only reason to include the readonly property in the header in the first place is to allow other classes to get the value, while only you are allowed to modify it. Quite often, that ivar should be of no concern to other classes, and is an implementation detail only. As such, it has no place in the header file.
Implementing this ivar as a private property (a new property only declared in the Class Extension) is still useful, because of the convenient memory management boilerplate code it can abstract for you. Unfortunately, name collisions are just a fact of life in Objective C. Apple lays out some pretty clear naming conventions for you to follow (or not follow) to prevent collisions with their method names. If you're worried about collisions with the getters and setters you've invisibly created with that private property, just adopt and obsessively follow some naming convention for those private property names that you only ever use when implementing a private property. That's the best you're going to do with Objective C, but I personally think the benefits outweigh the risks.

Use of #synthesize/#property in Objective-C inheritance

If you have Class A with an instance var "foo" which has a #property/#synthesize directive, and Class B inherits from Class A, does it also need to #property/#synthesize "foo"? The reason I ask is because when I try to use Class B's "foo", the calling class says that "foo" is not something of a structured union or a member, which makes me believe it needs to be explicitly synthesized.
No, you don't. Synthesized properties are added to class A and its subclasses automatically.
If you have Class A with an instance var "foo" which has a #property/#synthesize directive, and Class B inherits from Class A, does it also need to #property/#synthesize "foo"?
No.
The reason I ask is because when I try to use Class B's "foo", the calling class says …
No, the compiler says it.
… that "foo" is not something of a structured union or a member, which makes me believe it needs to be explicitly synthesized.
It is. In class A.
The compiler is giving you that warning because it doesn't know about the #property, which is because you have neither declared it nor imported a header that declares it. You say that class A's header declares the property, so import class A's header into class B's implementation, so that the compiler knows about the property when compiling class B.
Just in case this helps someone.
I came across this problem too and read these answers and still couldn't access super class variables directly. They were declared as properties and synthesized in the super class and and I had imported the header into my subclass. I was stuck until I discovered I needed to declare the member variables in the #interface section in the super class as well as a property of the superclass....! e.g.
#interface BuoyAnnotation : NSObject <MKAnnotation>
{
CLLocationCoordinate2D coordinate;
CLLocation* location;
int type;
}
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, retain) CLLocation* location;
#property (nonatomic, assign) int type;
WHen inheriting you should not need to redeclare any properties or variables.
Perhaps if you post your ClassB header file or a portion of then people can better pinpoint your problem.
Correct, you just declare a #property outside of the typical member variable declaration curly brackets and then #synthesize the property in the .m file. I did notice that in the child class you have use self.propertyName to reference it but in the parent class you can just use the instant variable name.