Best practice style -- method names with delegates and ownership - objective-c

Is it a good practice or a bad practice to have same-named methods across classes, particularly where inheritance and/or protocols are involved?
For example, I have a protocol of some kind:
#protocol DataReceiver <NSObject>
- (void)handleNewData:(id)data;
#end
And I have a controller class that owns some stuff, such as
#interface OwnerOfAllThings <DataReceiver>
//this child does NOT conform to DataReceiver
#property (nonatomic, strong) SomeOwnedModel myChild;
#end
But the child is opaque, so my implementation of -handleNewData: is basically just a pass-through and calls a method in the child that takes care of the actual handling. So my question is, although it's not functionally so different, is it a bad idea to put an identically named method in SomeOwnedModel, being that it might be confused with the declaration in the protocol? Or should it in fact be exactly the same, for consistency?
i.e., which is better (assuming that the SomeOwnedModel.h declares the appropriate method):
#implementation OwnerOfAllThings
- (void)handleNewData:(id)data {
//Option 1:
[self.myChild handleNewData:data]; //OR...
//Option 2:
[self.myChild ownerReceivedNewData:data]; //or whatever else
}
#end

Since OwnerOfAllThings is simply invoking the method in the child, I might be inclined to keep the same method names, possibly even have SomeOwnedModel conform to the same protocol. If you use the "use unique names" pattern, I can only imagine how unwieldy it would become if you had three or four levels of classes or if you had a ton of methods in your protocol, being forced to come up with arbitrarily unique names for each.
By way of example, I have NSOperation based framework for NSURLSession, with a session manager object (a wrapper for NSURLSession), and a bunch of individual NSOperation classes (one for download tasks, one for data tasks, etc.). In this case, while NSURLSession conforms to not only NSURLSessionDelegate, it also conforms to NSURLSessionTaskDelegate, NSURLSessionDataDelegate, etc. (because that's how NSURLSession works). But when this session manager receives one of these task-related delegate calls, it simply routes the event to the appropriate operation object. So to make this clear, I made the various operation objects conform to the appropriate protocol (e.g. download operation conforms to NSURLSessionDownloadDelegate, data operation conforms to NSURLSessionDataDelegate, etc.). The end result is that despite a dizzying collection of classes and protocols, the intent is unambiguous.
So, bottom line, if the parent is simply routing the event to the appropriate child and offering no material contribution beyond that, I'd be inclined to use same methods (and possibly same protocol). But if the parent class is offering something substantively richer/different, functionally, over what the child is performing, then a unique name would probably be appropriate.
As an aside, when coming up with your method names, I might suggest a method name that distinguishes "I received a bit of data and more may be coming" (i.e. didReceive...) vs. "I received all of the data" (i.e. didComplete...). This is an informal convention Apple uses in NSURLConnection and NSURLSession, and following it might be helpful to make your intent clear.

The best way to name a method is always to try to accurately describe (beware of excessive verbosity) what the method does. If both your methods do exactly the same it's probably a good idea to extract that functionality to a self-contained class.
Often the convention is followed in iOS to name delegate methods like the one you have shown in the following form:
-(void)dataSource:(DataSource*)dataSource didReceiveNewData:(id)data {
//Call your "child" object here
[self.myChild doAWithData:data];
}
Where dataSource is the object that calls the delegate method.
In my opinion you're running into this problem because you're not accurately describing what the method actually does by using "handle" data.
Perhaps a good source for standards is Apple's documentation.

Related

Objective-C - Effective Subclassing of Cocoa Class Clusters

I have an object that used to be an NSMutableSet but needed some more stuff attached to it. The obvious (and obviously not supported) thing to do is to subclass NSMutableSet and tack on the two additional properties. Since NSMutableSet, like basically all Cocoa data structures, is a class cluster I cannot subclass it in the usual way, since the super class just throws exceptions. This led me down several paths.
The first path was to create sort of a composite object that declared itself as a subclass of NSMutableSet but really just forwarded the invocations to an internal NSMutableSet. I didn't want to have to implement every method on NSMutableSet, so I thought forwardInvocation: would be a good way to accomplish my mission. Unfortunately, the abstract class of NSMutableSet implements all of the methods on the interface and their implementations throw exceptions, so I was never getting to the point where I could forward an invocation.
The second path was to subclass NSProxy and forward the invocation from there. This solution falls short in that I need to copy the interface of NSMutableSet over unless there's a way to declare "this class implements this interface" that I don't know about (this could very well be the solution).
The third path was to create a category on NSMutableSet and import it just for the class that needs to use it but that falls short since you cannot add non-dynamic properties via a category. That led me to using associated objects in a category. I'm willing to admit that that is the correct solution for this use case, but I wish it weren't since it's kind of clunky. It's doubly clunky since the properties I'm adding are primitive so I'll have to wrap and unwrap them when setting and getting the association (unless there's a way to associate primitives which I'm unfamiliar with).
Essentially, what I would like is something that behaves functionally as a subclass of NSMutableSet (and all class clusters) but cannot figure out the best approach. Thanks!
Trying to subclass Cocoa class clusters will just create an awful lot of hurt. It may seem a good idea, but you will forever run into problems.
Just create an NSObject with an NSMutableSet as the first member object.
Subclassing Cocoa class cluster is kind of discouraged. Not without reasons. Please do not enter this crashy world.
Either of your solutions will work. I've successfully used the first path with NSArray and NSDictionary, so I believe it should work fine for NSMutableSet as well. Just remember that you need to override not only forwardInvocation:, but a few of other methods as well. Please consult Surrogate Objects sections of Apple docs:
Although forwarding mimics inheritance, the NSObject class never confuses the two. Methods like respondsToSelector: and isKindOfClass: look only at the inheritance hierarchy, never at the forwarding chain.
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html
In my case, I've overridden:
conformsToProtocol:
isKindOfClass:
isMemberOfClass:
respondsToSelector:
instancesRespondToSelector:
forwardInvocation:
methodSignatureForSelector:
instanceMethodSignatureForSelector:
from which isKindOfClass:, conformsToProtocol: and respondsToSelector: are definitely crucial.
I've also used the third path with good results, but I admit the associated objects API is clunky.
First, gnasher729 is correct. Don't subclass class clusters. Just don't do it. Can you do it? If I tell you that you can't, will it help you convince yourself that you shouldn't? I can lie if it helps you make good choices.
But in all seriousness, it is almost always meaningless as well. Is your subclass really a specific kind of set? Or is it really kind of like a set. Consider NSAttributedString. It isn't a kind of string, it has-a string. This is almost always better.
And also, class clusters happen to be a royal pain to subclass.
That said, adding associated values onto a data structure, as you've already discovered, is generally just fine, because what you really want is "hey, I have some data that needs to go along with this other data." Wrapping has gotten so easy that it shouldn't really slow you down. See https://stackoverflow.com/a/14918158/97337:
objc_setAssociatedObject(self, animatingKey, #(value), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
And with "one weird trick", you can make this really easy:
#interface NSObject (BoolVal)
#property (nonatomic, readwrite, assign) BOOL boolVal;
#end
#implementation NSObject (BoolVal)
- (BOOL)boolVal {
return [objc_getAssociatedObject(self, _cmd) boolValue];
}
- (void)setBoolVal:(BOOL)value {
objc_setAssociatedObject(self, #selector(boolVal), #(value), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#end
But I'd still come back to the question of whether this is really a kind of set (rather than just like a set), and whether it really needs to respond to every message that can be sent to a set. As with NSAttributedString, your real needs are often much smaller than that in practice, and wrapping the handful of methods you need is often worth the simplicity and control.
For completeness, let's look at your first path:
create sort of a composite object that declared itself as a subclass of NSMutableSet but really just forwarded the invocations to an internal NSMutableSet
Can you subclass an NSMutableSet? Yes, but should you? The documentation for NSMutableSet says:
Subclassing Notes
There should be little need of subclassing. If you need to customize behavior, it is often better to consider composition instead of subclassing.
So weigh that up and if you want to subclass refer again to the documentation:
Methods to Override
In a subclass, you must override both of its primitive methods:
addObject:
removeObject:
You must also override the primitive methods of the NSSet class.
And looking at the NSSet class documentation we find its primitive methods are:
Methods to Override
In a subclass, you must override all of its primitive methods:
count
member:
objectEnumerator
That's it, 5 methods.
You can define your own class as a subclass of NSMutableSet, add an instance variable which is an instance of NSMutableSet, implement 5 methods and redirect them to the set instance, add whatever init methods you wish, and then add your additional properties.
If performance is of concern then the tradeoff is between redirecting those five methods and accessing associated objects for your additional properties. You'll need to profile to work that out, but if and only if performance becomes an issue.

confusion over Objective-c views, delegates, and outlets

I am trying to teach myself objective-c, but coming from a Python/Java background, it is proving very difficult. I tried to post a bunch of points I am confused on, but it was marked as too vague, so I'll break it into sections.
First, every example of a delegate and outlet I've found uses cocoa view code to get the idea across. Unfortunately, I don't yet understand enough of the code to grasp the example's point. So, can anyone provide a more basic example of a delegate? My understanding is that it is a way of subclassing; how is this better than traditional subclassing? Why does every cocoa project automatically include appDelegate.m? Can delegates be used for other purposes, not just GUI stuff?
Okay, I think I see. So a delegate is a class that conforms to the protocol of some other class. A protocol is simply a list of methods and variables that have to (or can, if set to optional) be implemented in the delegate class. To make a delegate, you have to use the #interface keyword, then the name of your delegate, then (in < > signs) the protocol name? So if class c1 wants to set itself up as a delegate of class c, class c must first specify a protocol, right? You would then be able to implement everything in c's protocol in c1:
#interface c1;
I feel like I'm missing some bits there, but hopefully I have the concepts right. :) This also explains the mysterious less- and greater-than signs; they declare what interface the delegate implements.
Outlets are similarly always tied to view code. They seem to be some kind of inter-object messaging system. Is that right? Again, an example of a basic outlet that is not mixed in with complex GUI statements would be great.
So outlets are never needed? I know that IBOutlet and IBAction are not needed except for use with Interface Builder, but I thought outlets were more general than that? The docs seemed to indicate that they are not even specifically for interfaces, but could be used for anything.
Thanks in advance for any help.
Update: Delegates don't have to conform to protocols. Protocols just make it easier to require some classes to have methods. It allows you to know for certain an object one has set as a delegate implements a certain method so you can call it safely, and allows the compiler to verify that method is indeed implemented (if you declare a delegate instance variable as id<SomeProtocol> delegate, the compiler will give a warning or error if you try to set delegate to an object of a class that doesn't conform to SomeProtocol.
Protocols help ensure safety, but they're not strictly necessary. A class can have a delegate (or multiple!), and they don't have to conform to any protocols at all.
As for outlets, no, they're specifically and only used with Interface Builder. The IBOutlet and IBAction keywords have no effect on code (they're even stripped out before compile time) - they're only markers for Interface Builder to look for so it knows which properties and methods should be accessible within the interface. The term 'outlet' is a direct reference to something marked as an IBOutlet, and is really not used in any other context that I can tell.
Again, it's okay if you don't understand this right away. Think it over a bit, and at some point, it'll just 'click'. I was caught up on delegates for a long time, just like this, before one day, I realized that delegates really aren't any special. They're regular objects referenced by other objects - it's just that this design pattern has a special name (delegation), and these objects are only called delegates. They could just as easily be called gyros or falafels, and the net effect would be the same. :P
You don't need to name an object delegate for it to be a delegate; it's just a convention.
About delegates: the first thing to understand, and this got me for a while until I had the proper "Aha!" moment, is that there is nothing special about a "delegate". The word "delegate" is just a title for a type of object that another class depends on, very often for content or decision-making. A developer will use a delegate when they don't want to (or can't) tie one of their classes to another class by name - it's an Object-Oriented way of decoupling and making classes more generic.
Now, very often, classes will require delegates to have specific methods they rely on, and one way to ensure that is with a protocol (more commonly known as an interface in Java). Protocols define a list of methods; classes "conform" to a protocol if they declare they do in their interface (e.g. #interface IFObject : NSObject <SomeProtocol> { ... }) and if they implement all the methods they're required to. Protocols can have optional methods as well.
This model is used often with view controllers, views, and the GUI in general because many AppKit and UIKit classes are written to be as generic as possible. NSTableView, for instance, implements the most basic behavior it can possibly implement without requiring any implementation-specific information; for the rest, it relies on other objects, ones that conform to the NSTableViewDelegate and NSTableViewDataSource protocols. Any object can conform to the protocols, as long as they implement the right methods (and in this case, a controller class will usually implement methods from both protocols, but it doesn't have to be so). In fact, one easy way to understand this topic better is to take a look at NSTableView - it's got a delegate property and a dataSource property, but in effect, they're no different. delegate could be called monkeyButt, and the concept would still work. The key is to not treat delegates as a black box - there's nothing special about them.
Delegates can be also used for non-GUI purposes; one concrete example, as you mention, is the app delegate. NSApplication sends a delegate notifications to let it know when the application has been launched (among other things), so it can set up shop. Again, any object can be a delegate to any other object, for any purpose. It's simply a convention.
Briefly about outlets: as others have mentioned, outlets are simply connections between an interface defined in an XIB and your code. They're a way of letting Xcode link up the interface to the appropriate elements so that when your application loads the interface file, it can load up the right pieces of code or execute them.
They're generally an easier way of setting up an interface - they're not strictly necessary (you can create an interface programmatically, without using an XIB file), but if you do decide to go the XIB route, they're how you relate your interface to your code.
A delegate is an object that is delegated some task by an object it declares itself the delegate of. Let's say an object does some task and then needs to notify the object that "owns" it, so to speak. In order to allow the object to work under any conditions, it cannot be allowed to know what type of object it should contact, so we set its delegate and adhere to its protocol. Setting the object's delegate is like saying "Here's the object I want you to use contact with the messages declared in your protocol. I promise the object actually implements the methods in the protocol." For example, you might see this.
#protocol SpriteDelegateProtocol
#required
- (void) projectionMatrix;
#optional
- (void) animation:(int)animationIndex willCompleteFrameNumber:(int)frame forSprite:(id)sender;
#end
#interface Sprite
#property (nonatomic, assign) id<SpriteDelegateProtocol> delegate;
#end
The interface for our sprite object declares that it has a property called a delegate, which is of type id. It can be any object, but it must adhere to the protocol in the triangle brackets. If it says it adheres to the protocol, it has to implement the methods declared under the #required and can implement the ones listed under the #optional. It's up to us to determine whether or not our delegate actually implements the optional methods using something like respondsToSelector:. We might even store the return value if we had a lot of methods to do that for.
The application delegate is special in that it is the delegate to our UIApplication object. It receives messages on application state, such as applicationDidEnterBackground:. You can see what methods are in the protocol adhered to by our application delegate here.
Delegates can be used with any object. Any object can say it has a delegate property to set, and that it must have the following methods as shown above. The protocol is essentially a portable interface that can be used to tell another object what we need it to implement so that we can call said methods to delegate some portion of functionality out to it. We can notify our delegate when a task has completed, ask it to give us information (typically called a data source instead of a delegate so that they can be different objects if you want) or ask it whether or not we should do some task at all.
An outlet is a way of connecting a view instantiated in a NIB or storyboard to a property in its controller. So, if you place a UIViewController into your main storyboard and change its class to MyGreatControllerSubclass then proceed to place a button in that controller's view, you might want to hook that button up to an "outlet" (property) in the controller's interface so that you can access the button from the controller later.
No delegates are not a way of subclassing. I also came from Java and have been doing O-C for almost 5 years now.
Delegates generally conform to Protocols, which are the equivalent of Interfaces. What's great about that is it leaves you a lot of flexibility in how you implement the things that are covered by the delegate. So for instance, you will see that Table Views can be implemented by extending UITableViewController or implementing the delegate. That way, if you have a composed view where a user is selecting items from one table and putting them into another, you can do a single controller and have it perform the delegation for both views.
The best way to think about delegates is as examples of message/event oriented callbacks. Have you ever heard the saying that what makes a Framework different from ordinary programming is, with a Framework, it tells you what it wants you to do to ensure the results you seek? That is what delegation is. I was doing a Collection View last night and could not get the edit menu to come up. Just provide delegation of three methods, know nothing about how the menu is invoked, where the Long Press gesture handler is, etc.
Note that Delegates are the glue that makes Dependency Injection unneeded in the O-C world. I prefer them.
Delegates are the common design pattern (http://en.wikipedia.org/wiki/Delegation_pattern), they are not objective-c specific.
Outlets make possibly the binding of Controller and View (GUI). May be you know the MVC paradigm (model-view-controller)? So you build your GUI (the View from MVC) with Interface Builder and bind the elements of this GUI such as Buttons, Text fields and so on to your Obj-C code (the Controller from MVC) using outlets.
Take a look at this post: Conforming Objective-C’s Protocols in C# Codes
Don't worry about the word "C#" in the title, you could just ignore that part. The main part of this post talks about protocols and delegates in Objective-C. This might be helpful.

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?

Sending messages to objects?

I have done this successfully many times before, but this time it just won't work.
The code in my .h file:
#interface Images : NSView {
}
- (void) draw;
#end
The .m file (of another object):
- (IBAction) go: (id) sender; {
[Images draw:nil];
}
When I try to compile this, it says the following:
'*' may not respond to '*
Images may not respond to '+draw'
This has me quite confused. Shouldn't this be working?
Please Note: Yes, I have seen the other questions about messages, but none of those answers was even partially helpful for me. After reading them, I was even more confused.
Your draw method is an instance method: it can only be called on instances of the Images class. In your go: method you're trying to call it as a class method—if this is what you want, change it to:
#interface Images : NSView
+ (void)draw;
#end
I think a review of some of the basic concepts of object-oriented programming is in order; namely the difference between a class and an object or instance.
A class, in the general sense, is a collection of data and the functions which act upon it. A class defines the interface that one uses to access and manipulate data that is logically grouped together, and serves as a blueprint for creating objects or instances. See http://en.wikipedia.org/wiki/Class_(computer_programming)
Instances of a class (objects) are the typical things you manipulate in an object-oriented program, and they are created from the class "blueprint" and follow the behavior as specified by the class.
A typical example would be a fruit- take apples for example. An imaginary Apple class would represent all apples in the general sense and would model properties such as color and size and actions such as wash and eat. An instance would represent one, single physical apple- a Granny Smith or Pippin or whatever variety.
Just as it doesn't make sense to wash or eat apples in the general sense of the word (the concept of apples, not the agglomeration), typically it doesn't make sense to tell a class what to do. You tell objects (individual apples) what to do.
The code you present above defines the class Images. The "-" in front of -(void)draw indicates that the draw method only exists for specific objects. It is an instance method in typical OO parlance.
Of course, in Obj-C it is also possible to send a message to a class without requiring an object. This is denoted by a "+" in front of the method name, as other answers indicate. This is called a static method and it typically used to control some shared behavior or aspect of all objects of that particular class.
The problem with your code is that you are declaring -(void)draw as an instance method but calling it as a static method. Which way you want to do things is up to you, and it's difficult to determine from your code what the intent of the Images class is.

Objective-C: Protocols

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