MacRuby: conforming to protocols - objective-c

I'm new to MacRuby (and Objective-C). Reading through some of the Cocoa documentation, I keep coming across parts that mention delegates conforming to protocols. So far, I keep setting my AppDelegate as the protocol for anything that talks about a delegate, but I'm not sure whether or not I'm conforming to the necessary protocols.
What do I need to know about Protocols and how do I conform to them in my application?

You need to understand what an [formal] Objective-C protocol is, including that it defines mandatory and/or optional methods. See Apple's Objective-C documentation. Protocols are a limited form of multiple inheritance whereby only behavior, but not state, is inherited. Other languages may call that interface or mix-in.
To conform to a protocol means that your class implements all mandatory methods, and possibly none, some or all optional methods.
Typically, protocol are used for delegates. It's a means to formalize the API that a class requires from its delegate. For a given delegate protocol, you need to understand that API. Refer to Apple's documentation regarding that specific protocol.
Finally, there is neither a way nor a need for you to declare that your MacRuby class conforms to any protocol. You can directly assign your class instance to the client object delegate. You are still required to conform to the protocol, but there won't be any compile-time checking. If you fail conforming, you can expect a run-time exception. Or some odd behavior. Or something.
That's my understanding anyway.

Related

Delegation in iOS without a protocol?

The Apple docs for Delegation state:
In both Swift and Objective-C delegation is often expressed with
a protocol that defines the interaction and a conforming delegate
property
I'm not sure of any other way to create delegates that don't "have to" involve a protocol. Is there another way of expressing delegation in Swift or Objective-C that doesn't involve a protocol?
A delegate doesn't have to conform to a protocol. You can code to an implementation, but that is bad practice.
I think apple are saying that this is the way things are normally done. You don't have to use protocols...but you should if you want to keep things flexible.
Delegation is in essence asking someone else to do something for you. If you enforce a contract, then its more likely they will do it for you.
I Completely agree with the above answer, protocols guarantee the contract between the two objects. If there was no protocol, you cannot make sure that delegate methods are implemented in a way you require them to be.
Even if you use a class instead of a protocol, there can be problems regarding multiple inheritance and the implementation becomes difficult. This also leads to tight coupling between the objects and memory management becomes difficult.
However, in my point of view you can implement delegation without a protocol this way :
Forget the protocol, one delegate and one delegating object.
Its is developer's responsibility to implement all the required methods in the delegate object.
The variable 'delegate' will be of type class instead of protocol.
Call the appropriate methods directly whenever required.

What is the point in having protocols if they are not checked?

I'm going through the book about Cocoa and Objective C ("Aaron Hillegass, Adam Preble - Cocoa Programming for Mac OS X - 2012") and when I did the example with NSTableView, I noticed that it really doesn't matter if I define my class as conforming to NSTableViewDataSource, NSTableViewDelegate protocols or omit them, only methods matter. (looks like sort of duck typing)
That is, the application works fine with both definitions:
#interface SpeakLineAppDelegate : NSObject <NSApplicationDelegate, NSSpeechSynthesizerDelegate, NSTableViewDataSource, NSTableViewDelegate>
and
#interface SpeakLineAppDelegate : NSObject <NSApplicationDelegate, NSSpeechSynthesizerDelegate>
It only yells at me at runtime if I don't implement 2 essential methods which are defined in NSTableViewDataSource, and in any case it doesn't matter at all if I put these protocols in class definition or not. So, what is the point in having them in the language? If they are only for documentation, we could put their names in comments as well, right? Or I'm missing something important here?
Protocol conformance can be checked at compile-time and runtime. Like most people said in the comments, protocol conformance is checked at compile-time. If you assign a type that doesn't conform to the protocol (other than id) to a variable of type bracketed with that protocol, the compiler should give you a warning. So in order to be able to pass an object that doesn't conform to a protocol to a parameter of that parameter type, you must have either 1) ignored a warning, or 2) gone through type id, which turns off static type checking.
The API you call also could (if it wanted to) check at runtime whether your objects formally conform to the protocol or not, using conformsToProtocol:. However, the convention in Cocoa is that the APIs never check for formal conformance to the protocol, but rather only check that it responds to a given selector when it needs to call it. This gives more flexibility to the user to, for example, use a class object (metaclasses can't formally conform to protocols, other than the ones conformed to by the root class) as a delegate.

objective c init in protocol

yesterday a colleague asked, why we should not declare an init method (initWith...:(...)) in a protocol to force implementing classes to supply such an initializer. I was quite suprised about that question and in my understanding, this is nonsense. But I could not find a definitive reason but that declaring an init method in a protocol leads to less flexibility for the implementations.
Could you please tell me a good reason, why there should or should not be an init method in a protocol?
Thanks!
You define methods in protocols so that your code could call methods implemented by others. The "contract" between you and developers implementing your protocol looks like this:
You define the protocol,
Someone else implements your protocol,
Someone else creates an object implementing your protocol, and gives it to you, so
You can call methods of your protocol without knowing their implementation.
In order to call methods of your protocol, you need to have an instance of an object implementing it. The whole point of defining protocols is removing from your code any knowledge about the class implementing your protocol: if you know which class you are going to get, you might as well skip the protocol, and program to the class directly. However, if you want to call your init, you have to either know the class, or someone else must pass you an alloc-ed object on which the init has not been called yet. Neither alternative is a good idea - the first one kills the purpose of having protocols, and the second forces your callers deal in partially initialized objects.
Note that it does not prevent you from having non-init configuration methods in a protocol: if all objects must be configured using certain bits of information, let your users implement whatever init that they want, and add a configureWith:... method to your protocol, letting you control the process of configuring the object without knowing about its init method.
I know some protocols in iOS SDK which has init... methods. For example NSCoding Protocol has – initWithCoder: required method. I think it is normal practice.

How do I discover which messages a delegate can / should implement?

In Objective-C / Cocoa how do I discover the messages I can implement in a delegate class?
From what I have read in the documentation a class will only allow certain chosen messages to be handled via a delegate but so far have found difficulty finding a list of messages for a class.
To ask the question another way, if I created a delegate for NSApplication, which messages are available for me to handle?
The documentation for NSApplication states a delegate
responds to certain messages on behalf of NSApp.
The documentation then goes onto say
NSApplication defines over twenty delegate methods that offer opportunities for modifying specific aspects of application behavior.
but as far as I can see it fails to list these methods / messages so how do I know which ones will be called from my delegate?
The delegate is usually supposed to conform to a protocol declared for that purpose, e.g. NSApplicationDelegate. If it's not clearly spelled out already, you can often find the name of the appropriate protocol by looking at the type of the delegate property (in this case, id<NSApplicationDelegate>). You can check the documentation for details on the methods, or the #protocol declaration in the appropriate header file for specifics on which methods are available and which are required or optional.
There are some cases where the object does not define a protocol for its delegate, for example NSURLConnection. In this case, you just have to follow the documentation of the class with respect to what it expects of its delegate.
In either case, it is completely up to the class when it sends a message to the delegate and what the semantics of any message are.
These methods are described in the NSApplicationDelegate documentation:
http://developer.apple.com/library/mac/#documentation/cocoa/reference/NSApplicationDelegate_Protocol/Reference/Reference.html
One quick note that is that it is useful to understand the difference between formal and informal protocols. Also formal protocols have optional methods, which needn't be called.
When you write your own protocol you will want to check -respondsToSelector: before sending optional/informal methods.
formal protocols are defined like...
#protocol SomeProtocol <NSObject>
-(void)someMethod:(id)sender;
-(void)someOtherMethod:(NSString*)aString;
#property(nonatomic,retain) someProperty;
#optional
-(BOOL)someOptionalMethod;
#end
and are adopted like...
#interface SomeClass : NSObject <SomeProtocol> {
}
#end
this tells the compiler that you are adopting SomeProtocol, and you wont be required to declare you methods for the protocol in the .h file, it also tell the compiler to warn you if you haven't implemented all of the required methods.
for informal protocols you don't adopt them syntactically, but you will need to declare your methods in the .h file.

Real world examples of #optional protocol methods

I'm learning Objective-C at the moment and have come across optional methods in Protocols. My background is C# and can see a Protocol as something similar to a C# Interface.
Where a C# Interface represents a contract, by advertising an Interface you are saying that you will implement the methods defined.
With this in mind I'm confused why you would ever need to define an optional method. This is not slur or an attempt to lessen Objective-C, I love Objective-C. I simply want to understand the benefits of these optional methods, in order to gain a greater understanding of the language.
I'd really appreciate it if someone could provide some real world scenarios (with sample code) where optional methods are useful.
I'll give you an example. I have a number of ObjC classes that talk to the Flickr API. One, called FKAccount can do lots of things related to a Flickr user's account including downloading the user's photos, getting their contact list and so on.
The FKAccount class defines a delegate protocol FKAccountDelegate. This protocol specifies a number of callback methods that FKAccount will invoke on its delegate depending on the success or failure of various network operations to Flickr. Not every application that uses FKAccount will be interested in every Flickr operation that FKAccount can perform.
If it were required that every class claiming to implement the FKAccountDelegate protocol implemented every method, you would end up with a lot of stub methods (FWIW, there are 41 methods defined in FKAccountDelegate). When these methods are declared #optional in the protocol, the delegate only need implement the callbacks it is interested in receiving.
The FKAccount class checks that its delegate responds to #optional methods in the protocol by:
if([self.delegate respondsToSelector: #selector(accountDidDownloadContacts:)]) {
[self.delegate accountDidDownloadContacts: self];
}