Objective-C: Protocols - objective-c

I'd like an instance variable object to adopt a protocol.
#interface GameScene : Scene <AVAudioPlayerDelegate> {
#private
Layer *content <CocosNodeOpacity>;
}
For example I'd like my Layer object to adopt the <CocosNodeOpacity> so that I can get the methods
-(GLubyte) opacity; //and
-(void) setOpacity: (GLubyte) opacity;
for free. The syntax shown above is invalid. Is it possible to achieve this without creating a new implementation file and creating a custom object? Thanks.

If these are all code you created, the best way to do this is probably to make the Layer class itself adopt the protocol, rather than the variable.
#interface Layer : NSObject <CocosNodeOpacity> { ... }
A key benefit to this approach is that the compiler will check whether you've implemented all required methods in the protocol at compile time, which is generally what you want. Adding the methods in same place as the rest of the standard class implementation is easier to understand (no hunting to find where the magical code came from) and less fragile than using categories (adding the same method via different categories can result in undefined behavior). As a general rule, I only use categories when I have to, such as adding methods to (closed-source) third-party code.
If you don't control the source of Layer, you may have to use this instead when you declare your ivar:
Layer<CocosNodeOpacity> *content;
Note that adopting a protocol allows you to statically type variables with a class type and get compile warnings if the methods aren't present. However, you don't get the methods "for free", since you still have to implement them. Still, judicious use of protocols and static typing can make your code more robust and "fail-fast" than using id as the type for everything. You are to be commended for not just taking the easy way out. :-)
For some details about protocols (including required and optional methods) see this SO answer.

A protocol in Objective-C is similar to an interface in Java. The protocol defines a set of functions and acts as a contract. It's like saying "I guarantee that whatever this object is, it has these methods."
You're pretty close on the syntax in your first code block. It would actually look something like this:
#interface GameScene : Scene <AVAudioPlayerDelegate> {
#private
Layer<CocosNodeOpacity> * content;
}
However, that doesn't save you from having to define the methods for opacity in your Layer class. Using the protocol, you've established that your class will have those functions, but you haven't actually provided them. You'll still need to write the code for them.
I think what you're looking for is an Objective-C category. A category provides a way to extend the functionality of any class by adding methods to it at runtime. They're possible because Objective-C is a completely dynamic language. If you aren't the author of the Layer class and can't easily add the opacity methods to it, a category is the way to go. In some cases, categories are extremely useful - you can add methods to built-in classes, like NSString and NSColor, without having the existing class source.
There's plenty of documentation for categories here on stack overflow. The apple docs are also very good. Here's an article to get you started:
http://macdevelopertips.com/objective-c/objective-c-categories.html

Related

Is it possible to extend(heritance) class in Objective-c as is traditionally conceptualised in other languages?

I am having a lot of repeated code throughout my app classes given that some properties & method are stable across all my views.
I am looking to extend whatever class I am working with so that it automatically inherit all properties and methods that I think should be common to those classes.
I looked into the apple guide on extending classes. But I am left confused in the terms of the level of heritance that I can achieve.
I've successfully created Categories on lets say a UIViewController. But that limits me to only be able to declare Methods. I can not declare Properties on my Category and call them in side my Category or in the Extended Class. I want to be able to declare Properties and use it inside and outside my Extended-Class.
Its my first time trying to extend a class in objective-c taking full advantage of heritance but I do not know if it is possible. Am I missing something?
As an example in the code below every time I try to instantiate activityIndicatorView inside my method _activityIndicator it wouldn't recognise it. I've tried #syntetize and #dynamic but it doesn't work
NOTE: I am seeking an answer based on how to achieve heritance of methods and propeties. not highlighting what categories cant do (as I already tried and know I cant have properties there)
My attempt went as far of
#import <UIKit/UIKit.h>
#interface UIViewController (customViewController1)
#property (strong, nonatomic) UIView *activityIndicatorView;
- (void) _activityIndicator;
#end
#import "UIViewController+customViewController1.h"
#implementation UIViewController (customViewController1)
- (void) _activityIndicator {
//......
}
Your question is too broad, plus it is not clear what your problem is. Yes, you can subclass in Objective-C.
This is all very well documented in Apple's document "Object-Oriented Programming with Objective-C", section "The Object Model", subsection "Inheritance".
Categories are a nice way to add functionality while at the same time conforming to an object oriented principle to prefer composition over inheritance.
Categories only add methods, you can't add variables to a class using categories. If the class needs more properties, then it has to be subclassed.
When you use the term “extend”, you're talking about creating a subclass. This is, IIRC, how the term is used in Java and some other languages.
Apple uses the term differently (as Hermann Klecker hinted in his first comment). They literally mean extending an existing class with more functionality (in the form of methods)—that's what categories do. This is the normal English definition; extending something in the real world generally does not create a new thing.
Objective-C supports subclasses, too; it just doesn't call them “extending” the superclass. It's called creating a subclass, which inherits from the superclass.
Strctly spoken you cannot add a property to an existing class any differnt than creating a subclass.
If you cannot halp yourself and subclassing is not an option, then you can extend the class with getters and setters for the property that you want to store within the class.
Instead of really storing it as a member/instance variable/property, which you can't do, you could store the object (it cannto be a scalar, must be an object) in the global space using objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy).
This is some sort of global dictionary with two keys, the key itself and the ojbect to which you want to associat the stored object to. In your case that is the object of the type of the exended class. The setter stores it there and the getter receives it from there using objc_getAssociatedObject.
You delete an association by sending nil as value to objc_setAssociatedObject
AFAIK retained associated objects (values) are released shortly after the object that holds the associateion (object) is deallocated.
For further details see the Ojbective-C Runtime Reference https://developer.apple.com/library/ios/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
Just: I do not say that this is strictly following the OO paradigm. :-)

Subclass NSArray in Objective-C

I need to have a class, which has all methods of NSArray, which behave the same way, but 2 methods are modified.
I want to override these 2 methods in my custom class:
1) countByEnumeratingWithState:objects:count:
2) objectAtIndex:
After hours of research I don't see any reasonable way to do that, because:
I don't want to use category, because not all NSArray instances should have the modified behaviour. (Plus that throws warnings)
I don't want to re-write all initializers plus all arrayWith... methods + the primitive methods + implemented my own storage (because this functionality is already implemented in Cocoa, right? Why would I re-implement all the functionality of a class that is already there?)
If I have my custom class inherit NSObject and use NSArray as storage in an ivar, then all NSArray's methods are not available when programming in Xcode (even if I can forward them to the NSArray ivar)
I had some success overwriting the method implementations on demand by using method_setImplementation(...), but still can't figure out a way to have dynamically a class created at runtime, which then will have custom implementation of the 2 methods I mentioned.
Looking forward to your ideas! Thanks
Mantra: If something is hard (or seems like it requires more code than is necessary), it is likely that your design is counter to the design principals of the iOS / OS X frameworks. It may yield a better solution to revisit your design.
To answer the original question, if you want to subclass NSArray (or NSMutableArray), you need to implement the primitive methods, no more, no less.
The primitive methods are the methods declared in the #interface of the class itself. I.e.:
#interface NSArray : NSObject
- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index;
#end
And for NSMutableArray:
#interface NSMutableArray : NSArray
- (void)addObject:(id)anObject;
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
- (void)removeLastObject;
- (void)removeObjectAtIndex:(NSUInteger)index;
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
#end
If you subclass NSMutableArray and implement the above 7 methods (the two from NSArray, too), you will have an NSMutableArray subclass that is compatible -- assuming your methods are correctly implemented -- with all APIs that consume mutable arrays.
This is because of the way class clusters are designed. The public classes are abstract; are never directly instantiated. They provide a primitive interface that contains the class's core functionality and then concrete implementations of all the other non-primtive API (save for the initializers, see below) that are implemented in terms of the primitives. Concrete, private, subclasses then override all the primitives and some of the non-primitives to provide optimal behaviors for specific configurations.
I want to have an NSArray instance for a library I'm working on and I
want to have it working transparently for the users of my library. Ie.
for them should be no difference between using a normal NSArray and
the modified class I'll be providing. Ie. it's a storage concern,
which the end users should not be concerned with and the interface
should remain the same as NSArray - therefore loosing all init methods
is not really an option at that point.
The initialization methods are not a part of the primitive interface to NSArray. You are adding a requirement above and beyond "make a class compatible with NSArray / NSMutableArray" as defined by the documentation. Nothing wrong with that, just pointing it out.
The reason why this is the case is because it is exceptionally rare to subclass the collection classes to provide the kind of business logic you describe. Collections are very generic in their behavior whereas such business logic that conditionalizes collection behavior would be done in a class that manages the overall model layer object graph.
If you really want to do this, provide an implementation of whatever init* methods you want, calling through to your wrapped generic instance as needed. There isn't anything so special about the implementations of the initializers that you are going to lose much in doing so.
No need to implement all of them, either. Implement one or two and #throw a descriptive exception on the rest.
If you do decide to forward the ones that accept var-args, you can't directly because there are no va_list accepting methods. Instead, you'll want to convert the va_list of arguments into a language array (i.e. id[] foo = malloc(... * sizeof(id));) and pass it to initWithObjects:count:.
Some other comments:
What you are doing [provide full NS*Array interface in a subclass] seems hard because it is not a common pattern and the framework designers saw no need to create a design to support it. Custom behaviors at the primitive collection levels are almost always better implemented at a higher level within the object graph. Almost always.
method_setImplementation() and dynamic class creation is academically interesting, but pretty much never a solution. Obviously, mucking with the NSArray or NSMutableArray classes (or the concrete implementation classes) is going to blow up the rest of the frameworks that rely upon standard behavior. Beyond that it, it is a pattern of dynamic OO composition that is not really intended to be used in Objective-C; it'll be a pain in the ass to maintain.
Instead of subclassing NSArray why not create a new class based on NSObject that contains an NSArray?
Then you can use all the functions of the NSArray and add your own methods that will do custom actions with it?
Or do you NEED an NSArray?

How do I implement a protocol generically with a category?

How do you decorate a class with some generic implementation of a protocol?
Sorry for what might be an obvious question. I'm new to objective c and so am still treading water just a little bit.
I've got a protocol for which I want a generic implementation:
#protocol SelectableElement <NSObject>
#property BOOL selected;
#end
I've got a couple of objects that I want to be selectable:
#interface Widget : NSObject <SelectableElement>
#end
#interface Duhicky : NSObject <SelectableElement>
#end
What I'd like to do is to write the implementation of the protocol once, and make sure that both objects implement it that way.
I don't think that I can write a generic category and bind it to both, so I guess one way of doing it is to add implement the category on the common class NSObject:
#implementation NSObject (Selectable)
- (BOOL)selectable
{
if (![self conformsToProtocol:#protocol(SelectableElement)]) return;
return YES; // Use associative storage for this?
}
- (void)setSelectable:(BOOL)selectable
{
if (![self conformsToProtocol:#protocol(SelectableElement)]) return;
// set this associatively?
}
#end
Of course, I can't define a property variable to do this, I would need to use the associative object store... which I've not demonstrated here.
Is this the only way of adding selectable behaviour generically to anything that implements the selectable element protocol? Or is there a more obvious way that I'm missing?
I can of course use inheritance to implement this simple example, but that would only work for implementing a single protocol in this way. Is this approach that I've suggested considered a natural fit, or is it a hack?
Joe
Make a class that implements the protocol ie. SelectableObject and then make the Widget and Duhicky classes inherit SelectableObject.
It sounds you want something like a Mixin in Ruby. Unfortunately, this is not possible on the language level in Objective-C. The only way to share behaviour is through inheritance.
That said, you could do some tricks with the Objective-C runtime to achieve what you want. It's probably not a good idea to work against the language you're using, but if you want to explore this option have a look here: http://cocoadev.com/wiki/MethodSwizzling
Sadly, this is one of those cases where inheritance is a particularly bad fit for the problem.
However, you can see this (ab)use of inheritance in the Cocoa frameworks (NSResponder or UIResponder). You'll run up against problems if you need to make an object selectable if you don't control the inheritance structure (some object in an external framework).
Your category on NSObject will work, and I would consider it preferable in this case. At first glance it seems heavy-handed for every object to carry around these methods, but the performance penalty is small due to caching in the method lookup mechanism.

If Protocol method is marked #required, when not implemented, why does compiler issue a warning and not an error?

Assume that:
New Protocol is declared
Method in this protocol is marked #required
Class conforms to Protocol
Class does not implement the method mentioned in Protocol
At compile time, information about this method is known: i.e. that it is required and that this class and any other classes this class may may extend do not implement it.
Why in this case the compiler issues a warning and not an error?
Errors are only issued when the compiler cannot continue because something went terribly wrong.
When calling a method in Objective-C, the method lookup is done during runtime and not during compilation, which C++ does. In Objective-C a "message" is simply sent to the object, something like obj.executeCommand("Hey, can you execute function <name> for me?"). In C++ the object will be called directly, in a way like obj.<name>(). In the case of Objective-C the executeCommand() method is called, which exists. In C++'s case the function is called but it does not exist. These are methods that are linked on the compiler level, which means they both become memory addresses rather than names. executeCommand becomes 0x12345678 but it still uses the same message ("execute function <name>").
This is probably very confusing, but it's related to the way methods are implemented in different languages.
If you feel strongly about it, why not turn on -Werror?
I don't know the real answer but here is a use case that would go against it.
What if you implemented all of the protocol methods in a category???
Main interface declaration adopts the protocol however the protocol method implementation is in a category.
This is valid code but will show compile error if compiler was that strict !!
Objective-C is a dynamic language. The idea of what an implementation is, is different to a static language.
For the most part, it's in code that most of us implement inside the #implementation ... #end block.
But what if a method is not found? Then an object has a chance deal with it dynamically.
Imagine you have an interface for a sound effect player:
#protocol FX
- (void)playBeep;
- (void)playSiren;
- (void)playHonk;
#end
An implementation could have the files Beep.mp3, Siren.mp3, Honk.mp3 to play, but instead of implementing each of the methods, it could override -forwardInvocation: and parse the selector string, something like this pseudocode:
NSString *selName = NSStringFromSelector([invocation selector]);
if ([selName startsWith:#"play"]) {
NSString filename = fileNameFromSelector(selName);
[self playSoundFileNamed:filename];
}
This may seem contrived, but once you start using the dynamic features of the language, you will start finding more and more places where it makes sense. And by sense I mean, does this effort help in the long run?
In the above case, just add a -sound* method name to the interface, and drop in a appropriately named sound file. It just works.
Another example from personal experiments: how to deal with Core Data entities in a more natural way. I want to do this:
NSArray *people = [Person findAllWithNameLike:#"B%"];
instead of mucking about with predicates, fetch requests etc.
But I don't want to define every permutation of method in code.
How about if I wanted to build an XML builder? I would look at a dynamic approach. It has served Groovy Builders well (look at Groovy/Grails for examples).
One last example: I have a traits system where I can define behaviours in the form of groups of methods and have my objects assimilate this behaviour. So, while the compiler doesn't see an implementation for the interface my object conforms to, the implementation is injected into it from a trait class, using the Objective-C runtime. Why would I do this? I find many delegate methods are boiler plate, but at the same time, a single base class for each situation is not flexible enough. Instead of cut and paste from code samples, my 'samples' compile and run :) and any changes are reflected across all projects using the trait.
To really understand why all this is available to you, it is worth playing around with a Smalltalk environment (search Pharo or Squeak). This is where Objective-C has its roots.
And finally, to stop these warnings:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wprotocol"
#implementation ... #end
#pragma clang diagnostic pop
Because there are times when there are bogus "required" methods in a poorly designed protocol.
They should have been optional but someone insisted they are "required".
Thusly making this a run time issue rather than a compile bug is very very wise.

Implement a pure virtual method in Objective-C

I want to go to there. Seriously though, how does one implement a pure virtual method in an "Apple" way? Do you use a Protocol with your base class and throw exceptions on those methods?
When you program in Objective-C you need to purge your mind of such things as virtual methods. You don't call methods on Objective-C objects, you send messages to them. Objects either respond to messages or they don't, but due to the dynamic binding, you can't tell this until run time.
Thus, you can declare a method on a base object and not not provide an implementation, no problem (except for the compiler warning), but you can't have the compiler flag up when you directly instantiate an object with such methods and it won't throw an error at runtime unless you actually send that message to the object.
The best way to create "virtual" base classes (in my opinion) is to declare the method and give it a stub implementation that throws a suitable exception.
In Objective-C, there is no pure virtual support as in C++.
A simulation would be that you declare a method in your interface but don't implement it in your .m file. Of course you'd get compiler warnings but IIRC you can turn those off. But you won't get warnings/errors if you don't overwrite them in the subclass, which you get in C++ (IIRC).
An alternative would be to implement them with just an NSAssert(NO, #"Subclasses need to overwrite this method"); body. Still, you'd only catch this at runtime, not compiletime.
Depending on what you're doing the delegate pattern may be more appropriate than a subclass, where the delegate is defined as id<YourDelegateProtocol>. The compiler will generate a warning if the required methods in the delegate protocol are not implemented.
Subclassing is generally avoided in Objective-C since objects cannot inherit from multiple superclasses but they can implement multiple protocols.
You should use the:
- (void)doesNotRecognizeSelector:(SEL)aSelector method.
As noted by Apple, here: https://developer.apple.com/library/mac/#documentation/cocoa/reference/Foundation/Classes/NSObject_Class/Reference/Reference.html
You have a few options, but you're on the right track.
ObjC doesn't support this directly, forcing subclasses to implement a protocol is the best way to check it at compilation.
'Secretly' implementing the method in the base class and asserting is what I do to confirm the subclasser has subclassed correctly at runtime. Some people have mixed feelings about assertions, or must leave them active, so that's not always a good solution.
You can also force subclasses use a specific class constructor and initialization sequence, then verify they have implemented everything required before returning an instance, in case compiler warnings don't cut it.
But ObjC is missing some lang features which allow clients to shoot themselves in the foot, or workaround what they wish so... you shouldn't get too stuck on enforcing it.
note: Exceptions are very uncommon (and a bit unsafe, too) in ObjC.
A virtual method is a method whose behavior can be overridden within an inheriting class by a function with the same signature (i.e same name with same number of params and type of params).
Example:-
#implementation BaseClass
-(void)viewDidLoad
{
[self virtualMethod:123];
}
-(void)virtualMethod:(int)param
{
//implement this method in subclass
}
#end
////////////////////////////////////////////////////
#interface ChildClass:BaseClass
#end
#implementation ChildClass
-(void)virtualMethod:(int)param
{
NSLog(#"There is no keyword "Virtual" in Objective C.");
}
#end
Output:-
"There is no keyword "Virtual" in Objective C."