Extensions/Categories instead of Interface - iphone

So I noticed that in my new Xcode projects, by default there was a category for my class in my .m file. For example, I'll have this in the .m file:
#interface ViewController ()
#end
#implementation
//Some code
#end
I was wondering is it okay to declare my variables and functions in the category in the .m file, or should I do that in the .h file like before. Basically, what are the best practices in respect to categories.
By the way, my question is sort of related to the below link, but that link does not completely answer my question.

This is not a category, it is a class extension (notice the empty parentheses). You can keep private implementation details, including private ivars, in the extension to limit the declarations in the .h file to the interface of your class. Note that you can add ivars only in the extensions, not in categories.
One very important consequence of this approach is that if you need ivars of types that require additional headers needed only for implementation, you can avoid including that header in the header of your interface, hiding implementation dependencies from users of your class.

Related

Objective-C Package level Property

I am creating an iPhone custom framework which should be able to be integrated into any iPhone app.
I have created some properties in one of the public header files of my framework. I want to give #package level access to those properties, so that those properties can be accessed only with in the classes inside the framework.
I do not want the user to use those properties.
Please tell me whether doing this is possible. If yes, please give me some idea on how to achieve this!.
First you should know that there is no way to completely forbid a user of your library to call a method. Even if you don't declare it in your header, a user could declare it on its own and use it. He would still have to find out the name of your property though, for instance by running classdump on your library.
Therefore in Objective-C, we make properties private by not declaring them in the header (which is the public part of your class), but by declaring them in the implementation (which is the "private" part of your class).
If you create another header which contains a category on your class, you can add some properties to it that will not be in the main header - so not on the public declaration of your class - but that can still be imported by other classes of your library that know about this header.
For instance:
MyClass+SecretProperties.h:
#interface MyClass ()
#property (strong) NSString *secretString;
#end
MyClass.m:
#import "MyClass.h"
#import "MyClass+SecretProperties.h"
#implementation MyClass
#synthesize secretString; // Depending on your runtime, you may not even need to this - properties are auto-synthesized in the latest SDKs.
…
#end
OtherClass.m:
#import "MyClass.h"
#import "MyClass+SecretProperties.h"
// Now you can use secretString on instances of MyClass
Then since you only export MyClass.h with your library, users have no idea that there is a secretString property :) This is the closest you can get to a #package scope AFAIK.
If you want to make those property as private then use below things.
In your .m file use extension characteristics of objective c.
#interface InitialViewController ()
//declare your property here
#end

Objective-C: Is a class just a .m and .h file?

I'm still coming to terms with classes and objects in Objective-C.
Is a class simply the combination of an interface and implementation file? Or, to put it another way, when would you say to yourself "I need a new .m file for this". At the moment I make a new implementation file when I want to put certain methods and variables in a separate place so that my main code doesn't become massive.
Any help would be greatly appreciated.
Strictly by convention and not by necessity, every new class should have an interface file (.h file) and an implementation file (.m file).
As far as using new .m files for distributing your methods, this is fine.
While convention dictates a pair of .h and .m files per class, the former containing the #interface and the latter containing the #implementation, there is no such requirement and, in fact, many of the system provided classes are divided across several files both in interface and implementation.
Technically, you don't need an #interface at all.
The absolute minimal class definition is:
#implementation Foo
#end
In that the above defines a class Foo that is a new root class. However, the compiler will warn about this.
Effectively, the minimal class definition is:
#interface Foo:NSObject
#end
#implementation Foo
#end
Note that NSObject is intentional; if you are going to make a class that will be compatible with the system frameworks or, even, the system runtime, inheriting from NSObject is pretty much required.
Syntactically, it is up to you as to how you separate the #interface and the #implementation. Traditionally, the interface goes in a header file such that others might #import it and use it while the implementation goes into a compilation unit -- a .m file -- to be compiled and linked exactly once.
But that is convention, not requirement. I've often defined a class --- #interface + #implementation -- entirely in a single .m file solely for use within the #implementation of some other class; effectively, a private class.
Note that class extensions -- #interface Foo() -- were expressly created to allow you to declare additional properties and methods on a class outside of the .h file's #interface Foo:NSObject. It allows a class to effectively have hidden API or to create a property that is publicly readonly and privately read-write.
No it's not. You can place multiple classes in a .h and .m file, althought this isn't deemed good practice.
In Objective-C classes are a pair of interfaces and implementations. These don't have to be in separate files but often are and it is a good way to keep your file structure clean. Often classes represent a little factory and when you have a group of functions that can be grouped together it is a good idea to put them in a class together.
I'll admit to occasionally grouping a few classes together, either with the definitions of all in one .h and the implementations in one .m, or, where some classes are "private", with the definitions AND implementations of "inner" classes in the .m of the major class.
I think it's sometimes good to avoid a proliferation of files this way, and to group interdependent classes together.
You can also go the other way -- spread the definition and and/or implementation of a class among multiple files using "categories" -- but that's a touch ugly and should generally be reserved for extending frameworks classes with specialized functions. (And even at that, done with some apprehension.)

Objective-C when to declare what methods in #interface

When and what methods should be declared in the #interface section of a class? As I understand, methods that describe what your class does should be declared in the #interface section, but other "helper" methods should not be declared. Is this a correct understanding from my side?
One way is to declare the instance methods in .h file. And, declare the private methods inside the .m, using a Category.
For example, in MyOwnClass.h file.
#interface MyOwnClass
- (void)aInstanceMethod;
#end
And, inside your MyOwnClass.m file, before the #implementation block,
#interface MyOwnClass (MyPrivateMethods)
- (void)aPrivateMethod;
#end
You usually should add your methods to the .h file when you want an external class to have access to it (public methods).
When they're private (only used internally by the class) just put them in your .m file.
Anyway, it's just a pattern. As Objective-C works with messages, even if you don't set a method in your .h file an external file can access it, but at least your auto-complete won't show it.
You should declare all your methods in your .h
The tip from EmptyStack is nice but it's just a tip.
If you don't intend to ship your binary as an SDK, you don't really need it.
Objective-C doesn't have (yet) private methods.

How to declare instance variables and methods not visible or usable outside of the class instance?

I've looked through a bunch of posts on this subject. Maybe I didn't run across "the one" and someone will point me in that direction. The question is simple and probably has a simple answer.
If you have two ivars, say, "public_ivar" and "private_ivar", where/how should you declare them so that what is public is public and what is private is not exposed in any way to anyone looking at the header file?
Same question in the case of "public_method" and "private_method".
I like clean header files (in other languages) that only expose the methods and ivars I want someone else to see. You should be able to publish your header file and not run into the danger of someone accessing something they are not supposed to. How do you do that in objective-C.
For example, let's say that I decide that I need to use an ivar to keep track of some data, a counter or somthing like that, between various class methods that all need access to this information. If that ivar is declared conventionally in the header under #interface its existence is publicly advertised and it is usable by anyone creating an instance of the class. The ideal scenario would be that this ivar would not be visible at all outside of the class implementation.
You can declare instance variables or declared properties in a class extension. Since a class extension is declared in an implementation file (i.e., not a header file), they won’t be visible to someone inspecting the header file. For instance, in the header file:
#interface SomeClass : NSObject
#end
and in the implementation file:
#interface SomeClass ()
#property (nonatomic, assign) int privateInt;
#end
#implementation SomeClass
#synthesize privateInt;
…
#end
or
#interface SomeClass () {
int privateInt;
}
#end
#implementation SomeClass
…
#end
Note that there’s nothing preventing access to private/class extension instance variables (or the accessor methods for properties declared in a class extension) during runtime. I’ve written a rather detailed post about this as an answer to another question on Stack Overflow: Does a private #property create an #private instance variable?
Edit: Instance variables in class extensions were presented in WWDC 2010 session 144.
Edit: "Using the Clang/LLVM 2.0 compiler, you can also declare properties and instance variables in a class extension."
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html#//apple_ref/doc/uid/TP30001163-CH20-SW1
Use class extensions to add to a class in your implementation file. A class extension is basically an unnamed category with a few bonuses: properties declared in it can be synthesized and anything declared in it must be in the main implementation, so the compiler can check to make sure you didn't miss an implementation. You must put the class extension before your implementation. You can't add instance variables directly in a class extension, but you can add properties. When you synthesize accessors for properties which don't have corresponding instance variables, the new runtime (os x 10.5 and later and all versions of iOS, I believe) will create the instance variables automatically. This means you can't create your own accessors, however, unless you put the instance variable in your header. Private methods can be added to the class extension without restriction, but as Anomie noted, it is technically possible to use them if you know what they are called, and with class-dump, nothing is safe.
Example usage of a class extension:
#interface MyClass ()
#property (retain) id privateIvar;
#property (readwrite) id readonlyProperty; // bonus! class extensions can be used to make a property that is publicly readonly and privately readwrite
- (void)privateMethod;
#end
#implementation MyClass
#synthesize privateIvar; // the runtime will create the actual ivar, and we just access it through the property
- (void)privateMethod {
...
}
...
Another way of creating "instance variables" without putting them in the header or using a property is to use associative references, which add data to an object at runtime. They aren't technically the same as instance variables, and the syntax for them is more complex. Since they also require the new runtime, there are only two reasons you would ever really want to use them: you want to add an instance variable in a category (outside the scope of this question) or you need it to be really really private. An associative reference doesn't create any methods or add to the class's definition in the compiled code, so if you don't create wrappers for them it is impossible to find out about them without asking the object after you add the data. See the bottom of the page I linked for a complete usage example.
You can use #private to specify that ivars are private. There is no way to make a method private, however. Even if the method is not listed in the header file, if someone knows the name and arguments they can call it.

Why does this code example on Apple's dev site declare three interfaces for the same class?

I'm diving into iOS development while trying to grasp Objective-C and I'm still in that phase where, ever where I look, I see things that don't make any sense to a veteran C programmer like myself. In this Game Kit example on Apple's dev site, one of the header files declares a class interface, three different times...
#interface SessionManager : NSObject <GKSessionDelegate> {
NSString *sessionID;
GKSession *myGKSession;
NSString *currentConfPeerID;
NSMutableArray *peerList;
id lobbyDelegate;
id gameDelegate;
ConnectionState sessionState;
}
#property (nonatomic, readonly) NSString *currentConfPeerID;
#property (nonatomic, readonly) NSMutableArray *peerList;
#property (nonatomic, assign) id lobbyDelegate;
#property (nonatomic, assign) id gameDelegate;
- (void) setupSession;
- (void) connect:(NSString *)peerID;
- (BOOL) didAcceptInvitation;
- (void) didDeclineInvitation;
- (void) sendPacket:(NSData*)data ofType:(PacketType)type;
- (void) disconnectCurrentCall;
- (NSString *) displayNameForPeer:(NSString *)peerID;
#end
// Class extension for private methods.
#interface SessionManager ()
- (BOOL) comparePeerID:(NSString*)peerID;
- (BOOL) isReadyToStart;
- (void) voiceChatDidStart;
- (void) destroySession;
- (void) willTerminate:(NSNotification *)notification;
- (void) willResume:(NSNotification *)notification;
#end
#interface SessionManager (VoiceManager) <GKVoiceChatClient>
- (void) setupVoice;
#end
I see that each interface is different, but specify the same class name.
What's the reason for this?
I've also noticed this same behavior in other code examples, only instead of declaring multiple interfaces in the header file, you'll see an additional #interface block declared towards the top of the .m implementation file, typically above the #implementation block. Why?
Thanks so much in advance for your wisdom!
These are called Categories, and you can see them by the parentheses after the class name.
They're used to group methods into chunks instead of having them all in one big bunch. They can also be placed separate from the main class declaration. This is particularly useful inside .m files, where you may need to create utility methods for your class, but you don't want them visible to other objects for any reason (so you don't put them in the .h, which is imported by the other classes). Another common use is to group methods which correspond to a certain logical category, informal protocol, or what have you. Categories can be named (#interface MyClass (MyCategory)) or anonymous (#interface MyClass ()). The latter is usually used for generic private methods in your header.
(The reason you need categories to declare private methods in your .m is so the compiler knows about the methods — otherwise, you'll get a warning when you try to call such a method.)
Also, you can use categories to add methods to existing classes. For example, UIKit contains a category on NSString called NSString(UIStringDrawing). Or if you wanted to make your own:
#interface NSString (MyFoo)
+ (NSString *)fooString;
#end
//... somewhere else...
#implementation NSString (MyFoo)
+ (NSString *)fooString { return #"foo!"; }
#end
Note that you can't add instance variables with a category.
It is not defining the interface 3 times - there is only one interface.
what you are seeing are categories that add methods to the class
There is a base interface that defines the attributes and some methods - there is only one of these ant it defines how the object is stored in memory and is the only one that is needed.
Objective C looks up methods at run time. These methods do not need to be found at compile time and thus do not need to be declared in headers/interfaces etc. If they are not declared and you code calls them then you will get compile time warnings.
In this case one category with an empty name is used for private functions. I usually only put this interface in the .m file of the class so is not visible to other code as not in a header.
The second category is to add the methods to make SessionManager meet the GKVoiceChatClient protocol. The usual reason for doing this is to group code covering a specific behaviour together.
Another reason for using categories is to add methods to an existing class like NSString -you can create your own category adding methods without subclassing the class as you have to do in many other OO languages including Java and C++
This is for code upkeep purposes i belive...its easier to looks through the different labeled interfaces, for example (VoiceManager) which is for voice manager setup and methods related to that, and you have the one interface dealing with the GK delegate methods and whatever interaction with gamekit there will be...as opposed to looking at one huge interface file and having to pick out what you are looking for...They can also divide the implementations in this way too so its easier to look through and navigate.
In order:
The first interface declaration is the actual interface declaration that declares the class as a subclass of NSObject and implementing the GKSessionDelegate protocol. It also declares the instance variables and a selection of methods.
The second interface declaration is a class extension. It can be thought of as a kind of anonymous category. So we'll skip it for now and come back to it.
The third interface is a category declaration. Categories allow you to do two things. They allow you to split the class implementation across multiple source files. In the above, you'll have
#implementation SessionManager
// methods declared in the first #interface
#end
#implementation SessionManager(VoiceManager)
// methods declared in the third #interface
#end
The two #implementations need not be in the same source file.
The other thing a category can do is allow you to extend already existing classes.e.g. #interface NSString(MyStringMethods)...
Coming back to the class extension, this is a bit like an anonymous category. The implementations of the methods declared in it must be in the main #implementation block. The purpose of the class extension is to allow you to declare private API separately from the class's header file. I normally put one in the.m file at the top if I have methods that should only be used from the class. Although, note that this is only a compile time restriction. There is nothing to stop a class extension message from being sent by anybody at run time.