I want to extend a class using category NSArray+Populate.h:
#interface NSArray (Populate)
-(NSArray *) populateArray;
#end
How can I detect the situation if there is another category (from another module or library), extending NSArray with method having the same name ?
For example, if there is a NSArray+Fill.h:
#interface NSArray (Fill)
-(NSArray *) populateArray;
#end
As I understand, the run-time engine will choose one of the version silently, without any crash ?
You cannot detect this situation and you cannot determine which implementation of -populateArray takes precedence. Some developers prefer to prefix their category method names for this reason.
Quoting The Objective-C Programming Language document,
A category cannot reliably override methods declared in another category of the same class.
This issue is of particular significance since many of the Cocoa classes are implemented using categories. A framework-defined method you try to override may itself have been implemented in a category, and so which implementation takes precedence is not defined.
Related
I have a subclass of NSMutableArray which in fact deals with a certain type of data i.e. say Employee. The problem is I don't like the inherented names of addObject insertObject and etc. and want to change them to something like addEmployee insertEmployee.
How should I deal with this?
If you are not going to inherit the methods of the superclass then you should not use that superclass!
When you inherit it is a 'is a' relationship between the sub and super classes. "Employer is a NSMutableArray" - no, that is not true and thus don't make Employer a subclass of NSMutableArray. Additionally, in the future you might use a dictionary to store employees (like mapping 'name' -> 'employee') and then having the representation being inherited as an array simply won't work.
#interface Employer : NSObject {
NSMutableArray *employees;
}
- (void) addEmployee: (Employee *) employee;
#end
Like such. Now addObject: isn't workable on instances of Employee; only addEmployee: works. Additionally, you'll only want to specialize methods like filteredArrayWithPredicate: eventually - so it won't be an advantage to inherit them.
You add a method addEmployee: and in that call addObject:. Similar for insertObject:
You can inherit NSMutableArray and add methods like -addEmployee: then add this in your .h file:
- (void)addObject:(id)anObject __attribute__((unavailable("Use -addEmployee:")));
This is a clang extension which will cause a complier error.
References:
How do I flag a function as being deprecated in an iPhone Objective C header file?
http://clang.llvm.org/docs/LanguageExtensions.html#messages-on-deprecated-and-unavailable-attributes
This question already has answers here:
What is the Objective-C equivalent of a public get/protected set property in C#
(3 answers)
Closed 9 years ago.
I have got two classes, Class1 and Class2, the second one inherited from the first one. I need to override -update method of Class1 to achieve my goals. The changes of -update method in inherited method are performed in the middle of code, so I can not use [super update]. Thats why I need to copy-paste original method from parent to inherited class. This method is using private methods of parent, so when I am trying to do overriding, I got warnings about absence of private methods because Class2 imports only Class1.h. To clarify, here is the code:
Class1.h:
#interface Class1 : NSObject
-(void) update;
#end
Class1.m:
#interface Class1 (Private)
-(void) private1;
-(void) private2;
#end
#implementation Class1
-(void) update
{
[self private1];
[self private2];
}
-(void) private1
{
// some code
}
-(void) private2
{
// another code
}
#end
Class2.h:
#interface Class2 : Class1
-(void) update;
#end
Class2.m:
#implementation Class2
-(void) update
{
[self private1]; // warning here
// do my own stuff between private methods, that is the reason of inheritance
[self private2]; // warning too
}
#end
Also, Class1 is not in my ownership, it is the one from open-source library (Cocos3D, to be precise), so I could not change it (and that is why I do inheritance).
The question is: how can I remove warnings? The only solution I can see is to copy private methods' signatures to Class2, but it seems to be a dirty trick. Or, it would be perfect if somebody points not how to remove warnings, but how to achieve my goal in changing method more nicely.
No need for swizzling, performSelector: or any other runtime buggery.
Just move or copy this:
#interface Class1 (Private)
-(void) private1;
-(void) private2;
#end
To the beginning of your subclass's .m file.
Normally, when trying to achieve something like an #protected scope for methods, the declaration of such would be in a header file like Class1_Private.h and that header would be set to the private role in Xcode.
As others have noted, exposing a private method via this mechanism is a bit dangerous. Given that Cocos2D is open source, that danger is mitigated somewhat or you could always just modify it directly. Of course, doing so means you effectively have a branch, which is costly to maintain.
If this is something that other developers are likely to do, I'd suggest filing a bug with Cocos2D requesting that the methods be exposed for subclassing purposes.
The way Apple does this is to make any methods that can be overridden in a subclass public, but document the fact that they shouldn't be called directly and are only there to be overridden. Documentation for Apple's code is (usually) comprehensive, and often referred to, so this works. Of course, typical third party code isn't as well documented, nor is documentation as likely to be read...
Another solution: I often create a second header called "MyClass+SubclassMethods.h", and publicly declare subclass-overrideable, but otherwise private methods in a category there. In source files for users of the base class and subclasses, this isn't imported, so the methods stay (effectively) private. In subclasses of the base class, I import "MyClass+SubclassMethods.h" to allow me to override/call these methods. It's not a perfect solution, but without the notion of 'protected' methods in Objective-C, I'm not sure there's a much better one.
A category, as suggested in another response is a good solution given that Class1 cannot be modified. If it were possible to make adjustments to source, a class extension declared in a separate header file and #imported in both the Class1 implementation, and the Class2 implementation file would be the way because then you can share not only private methods but also instance variables marked #public or #protected this way. Find out more about class extensions from here:
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html
Briefly, a class extension is a bit like a category (sometimes called a private category) but it can only be declared in the same compilation unit where the class it extends is implemented, and it can declare (and auto-synthesize) properties and instance variables. There's a source code template included in Xcode for creating class extensions (see below.)
You should be able to solve this problem using categories to extend your original class and try method swizzling to achieve your desired behavior.
I'm looking to create a class in Objective-C for an iOS project that is focused on fetching data. I'm familiar with how classes normally work, setter and getter methods and variables. However, for this class since it's only performing a function (returning NSMutableArrays) I don't want to have to create an instance of the class to use the methods inside the class.
Any idea how I can do this neatly and efficiently?
This is a little bit atypical in Objective-C. Since classes in Objective-C can't actually have state beyond what is available to ordinary functions (i.e. there are no class variables), a class that's never instantiated is relatively useless in most cases. The normal design patterns for this kind of functionality are:
A singleton class (if you need lots of state)
A set of functions (if you don't)
You want to make class methods?
#interface Foo : NSObject {}
+(NSMutableArray*)someClassMethod:(id)params;
#end
...
#implementation Foo
+(NSMutableArray*)someClassMethod:(id)params {
// whatever implementation
return nil;
}
#end
...
NSMutableArray* array = [Foo someClassMethod:nil];
If you're only performing functions, and you don't need to support subclassing etc, why not just write them as C functions rather than a class with methods?
If this is just a class that performs some functions, you could write it as a C function.
In your header file --
NSMutableArray *functionThatReturnsMutableArray(NSObject *param1, NSString *param2);
In your implementation file --
NSMutableArray *functionThatReturnsMutableArray(NSObject *param1, NSString *param2)
{
...
return aMutableArray;
}
And that just include the .h file in your class that needs these functions and call them directly.
NSMutableArray *anArray = functionThatReturnsMutableArray(param1, param2);
Depending on what you are doing (the same NSString operations, UIView manipulations, etc), you could implement a category (I answered a question yesterday with the explanation below -- copied for your convenience ;).
Categories extend an existing class with additional methods or with your version of existing methods. For example, let's say you want to add a method that returns the first letter of a string to NSString. To do this you would create a category as follows:
Interface - JULString.h
#import NSString
#interface NSString (JULString)
-(NSString *) firstLetter;
#end
Implementation - The typical convention is that the filename of the category is the name of the class you are extending followed by “+” and the name of the category. In this case the file would be called NSString+JULString.m
#import "NSString+JULString.h"
#implementation NSString ( JULString )
- (NSString *)firstLetter
{
return [NSString stringWithFormat:#"%C", [self characterAtIndex:1]];
}
#end
The neat thing about categories is that now they extend the behavior of ANY instance of the class you are working with. In other words, any NSString in your application will have your new methods (provided that you import the proper header file of course). Beware though, as with great power comes great responsibility. Overwriting class using a category behaviors may lead to undesired effects, so be cautious.
A couple of links you may want to check are:
Apple's guide to Objective-C
Learn Objective-C
Note:
I don't have my Mac with me so I'm writing this code basically off the top of my head (and using some code from the sites above as a reminder). So I apologize in advance for any mistakes ;)
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.
Can a Objective c interface have more than one implementation? Example I could have a interface but 2 implementations one where i use an arrays or another where I use a stack..etc to implement it.
If so how do you call it / syntax?
Objective-C has the concept of a Protocol, which is the specification of an interface. Through Protocols, Objective-C fully supports multiple inheritance of specification (but not implementation). So, a bit confusingly, the #interface syntax actually defines the class (implementation), which only supports single inheritance, but can specify the implementation of many / multiple inheritance of Protocols, or specifications of interfaces. In the end, this is very similar in nature to Java.
For example:
#protocol SomeInterface
- (void)interfaceMethod1;
- (void)interfaceMethod2;
#end
#interface SomeClass:NSObject <SomeInterface>
#end
#interface AnotherClass:NSObject <SomeInterface>
#end
Instances of either SomeClass or AnotherClass both claim that they provide the implementation required for the SomeInterface protocol.
Objective-C is dynamically typed and doesn't require that the object actually specify the message being sent to it. In other words, you can indiscriminately call any method you would like on SomeClass, whether it is specified in it's interface or any of its protocols or not (not that this would necessarily be a productive or positive thing to do).
Therefore, all of the following would compile (although with warnings) and run fine, although the messages / methods without implementation is basically a no op in this case. Objective-C has a fairly complicated (and very cool) process of handling method calling / forwarding that is a bit beyond the scope of this question.
SomeClass * someObject = [[SomeClass alloc] init;
[someObject someUnspecifiedMethod]; // Compiles with warning - no op
[someObject interfaceMethod1];
If you wish to define something that can be any class (#interface) type but implements a specific interface (#protocol), you can use something like this:
id <SomeInterface> obj;
obj could hold either a SomeClass or AnotherClass object.
Perhaps you should try Cocoa pattern called Class Cluster. To start using it you need to create public class called SomeClass and two private subclasses SomeArrayClass and SomeStackClass. When you need to use stack your public class constructor will create instance of SomeStackClass and will return it as publicly available instance of SomeClass.
(If you give this a vote, please give Roman a vote -- his answer was first, is correct, just lacked an example).
You are talking about a Class Cluster. For an example, look at the NSString class.
There is NSString:
#interface NSString : NSObject
And NSMutableString:
#interface NSMutableString : NSString
Both of which declare an extremely small set of methods in the core class's declaration. If you were to subclass NSString to implement your own string class, you would only need to implement those core methods. All other methods implemented in NSString are implemented in terms of those core methods. And, likewise, the mutation methods are implemented using the primitive methods declared in the core of NSMutableString.
Now, obviously, implementing all mutability via - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)aString (the one core method) would be grossly inefficient. Thus, at runtime, you'll note that you never actually have an instance of NSString or NSMutableString, but only instances of subclasses (which, actually, aren't really subclasses... but they might as well be in the context of this discussion).
And those subclasses -- the implementation class used at runtime -- overrides almost all of the methods of NSString and NSMutableString to provide highly optimized implementations of the specific operations.
So, you would do something like:
#interface MyAbstractClass : NSObject
... declare factory methods here ...
... declare core methods here ...
#end
#interface MyAbstractClass(AdditionalFunctionality)
... declare convenience here ...
#end
Then, in the implementation, implement all of the core methods as #throw #"Must use subclass" and all AdditionalFunctionality methods in terms of the core methods.
This could be entirely private -- not in a header at all, even:
#interface MyStackClass : MyAbstractClass
#end
#implementation MyStackClass
... implement the core methods and override the additionalfunctionality methods that need optimization ...
#end
Repeat for your additional types of classes. Then, implement factory methods on MyAbstractClass that return instances of the subclasses, as needed.
You mean for example like this:
#interface MasterViewController :
UIViewController <GKPeerPickerControllerDelegate,
GKSessionDelegate,
UITextFieldDelegate,
UITableViewDelegate,
AVAudioRecorderDelegate> {
}