Declare interface inside implementation file (Objective-C) - objective-c

In the last verson ox xCode (4.3) I've seen that prefdefined templates (such us Master/Detail template) in which the interface declaration is made in the .m file. For example, in the file MyFile.h there is:
#interface MyFile
#property (nonatomic, retain) NSString *someProp;
#end
And in the MyFile.m file there is:
#implementation MyFile
#interface MyFile {
NSString * anotherProp;
}
- (id) init...
Why it's made on this way? Why the anotherProp isn't declared into the MyFile.h file?
Thanks in advance

Well its not declared this way but this way :-
#interface ClassName() {
Declarations;
}
Methods;
#end
These are called class extension.They are similar to categories but can be declared only in implementation of the class not in any other class.The use of extensions is to redeclare property that is public or readwrite , also declare newer ones , if needed.They simply allow you to declare properties and variables in places other than #interface so the name extensios.
It was inrtoduced to tackle the problem with categories as they make the methods public and data hiding capability of classes is compensated but a class extension effectively extends the class’s primary interface which the declared methods have the same requirements as methods declared in the class’s oft public primary interface.

Related

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

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.

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.

Inheriting accessors in Objective-C

this is my first post; this site has been an invaluable resource.
I'm fairly new to objective-c so please bear with.
So I have a base class with a few properties which I want "private" so I made them readonly. To be clear, I don't want them mutable externally, but I DO wan't to use the 'set' accessor within this class. So...
// .h file
#interface Vehicle
#property (nonatomic, readonly) int speed;
#end
Also I repeated the property declaration within a category interface block to make the accessors writable in this class
// .m file
//Private properties and methods
#interface Vehicle()
#property (nonatomic, readwrite) int speed;
#end
#implementation
#synthesize speed = _speed;
- (void) someMethod {
[self setSpeed:10]; // Works fine
}
#end
But now if I inherit this class the derived class no longer has the set accessor method (setSpeed in my case). Do I need to synthesize again? Seems like that would defeat the purpose of inheritence. I know i can modify the instance variable directly (_speed = 10;) but would rather not. I'm sure there's something wrong with my understanding. Thanks!
// Example
#interface Ship : Vehicle
#end
#implementation
- (void) someOtherMethod {
[self setSpeed: 2]; // DOES NOT WORK, would like it to
}
#end
But now if I inherit this class the derived class no longer has the set accessor method (setSpeed in my case).
Actually, it does have the set accessor, it's just that the compiler doesn't know about it. You have a choice:
put the class extension (the #interface Vehicle() .... #end bit in a separate header file that gets imported into the .m for Vehicle and its subclasses (or use a category)
redeclare the read/write property in a class extension for the subclass. To avoid a warning, use #dynamic speed in the subclass's implementation.
Since there is no such thing as 'protected' methods, you need to create a private shared header where your anonymous category goes. Then both your original implementation and your derived classes include this header to get access to this 'private' stuff.

Make an iPhone property read-only in iOS objective-c

OK basically I have a class in an iPhone app where I want it to some read only propertys. Meaning that the owning class can read and write the property, but other objects can only read it. I try the "readonly" option when I declare the property, but then my class can't even write it. What use is that?
Let's assume you wanted to create a property called foo, an int, in your class YourClass.
Do this in your interface (.h) file:
#property(readonly) int foo;
Then in your implementation (.m) file, set up a class extension where you can re-define your property.
#interface YourClass()
#property(readwrite) int foo;
#end
This results in the property being readonly publicly, but readwrite privately.
Then, of course, you synthesize foo in your implementation that follows.
#synthesize foo;
If it's not too inconvenient, just use the ivar or "backing" variable in your class to modify the value. Like this:
In your .h file:
#interface ClassName
#property (readonly,nonatomic) NSInteger readOnlyValue;
#end
In your .m file:
#implementation ClassName
#synthesize readOnlyValue = _readOnlyValue;
_readOnlyValue = 42;
#end
While you could go the route of direct iVar access as described in other answers, a better solution is typically to use class extensions. They were designed exactly to solve this problem and, by using them, you can easily refactor your code later to expose the readwrite definition of the #property to other classes in your app without exposing it to all classes.
I wrote up a detailed explanation a while ago.
You can implement your own setter in the .m class or synteshize as:
foo = _foo; so you can call _foo (private variable) internally
On further reflection, the easiest way to achieve this is to add a normal property in a class extension, then declare just the getter in the header. E.g.
Interface:
#interface MyClass: NSObject
- (NSString *)someString;
#end
Implementation:
#interface MyClass ()
#property (nonatomic, retain) NSString *someString;
#end
#implementation MyClass
#synthesize someString;
#end
You'll be able to get and set, using dot notation or otherwise, and directly access the someString instance variable within the class, and everyone that has sight of the interface will be able to get, using dot notation or otherwise.

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.