Can a category implement a protocol in Objective C? - objective-c

I have a category on NSDate and it would be convenient if it could implement a protocol I previously created. Is this possible? what's the correct syntax for this?

Yes, that's possible. The syntax is:
#interface NSDate (CategoryName) <ProtocolName>
#end
#implementation NSDate (CategoryName)
#end
Here's Apple's documentation on the topic.
It's also possible to do this using a class extension. I very much like this to privately conform to delegate protocols. Doing so hides the implementation detail of being some delegate of some class from the public interface and removes the dependency from the header.

Related

Proper use of Objective-C protocols

I'm using my free time to play with Objective C. I was reading about Protocols but I'm afraid I might be using it wrong, considering I'm using it the same way (almost the same at least hehe) I do with C# code.
So, here is what I got. I have a protocol, a class manager to weakly couple my views and two views that implement the protocol.
#protocol IView <NSObject>
- (void) loadViewToScreen;
#end
#interface ViewManager : NSObject
#property (atomic, weak) id<IView> document;
#property (atomic, weak) id<IView> browser;
//Singleton
+ (id) getInstance;
#end
Then I call one view the views from each other.
ViewManager *vm = [ViewManager getInstance];
[vm.browser loadViewToScreen];
I'm not interested here what the best way to load views into the screen. It's just a mock code to test protocols.
I could not get the manager to use pointers to the protocols. So I'm afraid I'm getting view copies around. Did I get this right?
Thanks,
Lucas
A protocol, concpetually, is just a part of the type of an object or class. You can't get a pointer to a protocol. (Well, actually you can obtain a protocol object, but that's runtime mocking which doesn't seem to be what you want).
Don't be afraid about getting copies, though. Unless you copy an object or assign it to a copy property, you'll get pointers to the same instance.

Need assistance understanding objective-c protocol

#import <UIKit/UIKit.h>
#protocol myProtocol <NSObject>
-(void)aMethod;
#end
#interface ViewController : UIViewController
#property (weak) id<myProtocol> dSource;
#end
I am trying to get a firm grip on Obj-c protocols, I am reading apple doc to study, few things are not clear to me. Below are the points from doc:
The pie chart view class interface would need a property to keep track of the data source object. (The code above, we mostly declare protocol this way, when I have protocol declared in my class why need a tracking object, Or protocol can be defined in independent class? and for that we need tracking object?)
By specifying the required protocol conformance on the property, you’ll get a compiler warning if you attempt to set the property to an object that doesn’t conform to the protocol.
If you attempt to call the respondsToSelector: method on an id conforming to the protocol as it’s defined above, you’ll get a compiler error that there’s no known instance method for it. Once you qualify an id with a protocol, all static type-checking comes back; you’ll get an error if you try to call any method that isn’t defined in the specified protocol. One way to avoid the compiler error is to set the custom protocol to adopt the NSObject protocol.
I dont understand this question
Correct, the property requires that the property is an id which
conforms to your property, if you try to set it to something else
the compiler rightly complains
This is because respondsToSelector: is a method on the NSObject
protocol, so you can either have your protocol extend NSObject
(standard), or you could declare the property as
NSObject

Can we not declare methods in the header files?

I am watching the Stanford University iPad and iPhone application Developments course video. The instructor says in the video we can control-drag an UI object to the implementation files to create an action. But in this way the method will not declare in the header file. Does this mean it is ok to implement methods in the .m file but not declare in the .h file?
Depends on how you define "ok" :-)
Objective-C uses dynamic method lookup and does not really enforce access ("private", "public", etc.) specifiers. So you don't need to declare any method in a header file.
However you will end up fighting the compiler as it does do a fair amount of type-checking unless you persuade it not to, and you'll lose by doing so.
You are not required to declare in the header file all methods in the implementation. But if not in the header file obviously you cannot reference them by literal name in another file, nor can you "forward reference" them in the implementation file.
(Note that this is not that different from regular C, but is different from methods of a class in C++.)
It's "OK" to not declare methods in the header yes, under certain circumstances. For instance, if using ARC then the compiler generally needs to know the method signature so it can do the right thing. But basically all it means is that wherever you're using the method, it must already know about the method you're calling.
Since you're talking about Interface Builder, that's slightly different in that it will know about all methods since it can "see" the whole context of your header and implementation files and know that a method exists. i.e. in my terminology above, the method has been defined before it's used.
With regard to defining before use, the general accepted approach is to either:
Define a method in the interface file (.h). e.g.:
MyClass.h
#interface MyClass : NSObject
- (void)someMethod;
#end
MyClass.m
#implementation MyClass
- (void)someMethod {
// do something
}
#end
Define a method in a class continuation category. e.g.:
MyClass.h
#interface MyClass : NSObject
#end
MyClass.m
#interface MyClass ()
- (void)someMethod;
#end
#implementation MyClass
- (void)someMethod {
// do something
}
#end

Is Delegators really Categories in Objective-C?

I'm trying to understand the Informal protocols, until now I know that Informal protocols are a kind of Category, but, why delegators don't have a category name?
Example:
#import <Cocoa/Cocoa.h>
#class FileSystemNode;
#interface AppController : NSObject { // Where is the Category ????
#private
IBOutlet NSBrowser *_browser;
FileSystemNode *_rootNode;
}
#end
Thanks.
Informal protocols are not "a kind of category".
If a class conforms to a protocol (for example #interface MyClass <MyProtocol>) it is guaranteed that you can call all methods on that class that are required by MyProtocol. (Unless the class doesn't really implement them [the linker can't know that because of dynamic binding], which is a programming error and a lie, but that is usually not the case.)
Categories on the other hand allow you to take an already existing class and extend it with new methods (for example adding a removeAllSubviews method to the already existing NSView class).
So, categories and protocols are quite the opposite of each other.

How do I define a category that adds methods to classes which implement a particular protocol?

I want to add some methods to subclasses of NSManagedObject that implement the SOManagedObject protocol. I've tried defining it like this:
#interface NSManagedObject <SOManagedObject> (MyExtensionMethods)
...
#end
...but that doesn't seem to be valid. How do I define a category that adds methods to classes which implement a particular protocol?
Defining such a category on all such classes in general is not easily solvable. But your actual problem seems simpler: How does one add a category method to NSManagedObject for use only with subclasses that implement <SOManagedObject>? This is solvable.
What you want to do is add the method to NSManagedObject, then check that the instance you're working with can handle the messages you want to send it from <SOManagedObject>.
Let us suppose that we are given:
/* SOManagedObject.h */
#protocol SOManagedObject
- (void)frobble_so;
- (void)bobble_so;
#end
Now let's add a category method to all NSManagedObject subclasses that implement SOManagedObject:
/* NSManagedObject+SOConvenience.h */
#interface NSManagedObject (SOConvience)
/* Frobbles and bobbles - no effect on non-<SOManagedObject>-conforming
* instances. */
- (void)frobbleAndBobble_so;
#end
To do so, we implement the method like so:
/* NSManagedObject+SOConvenience.m */
#implementation NSManagedObject (SOConvenience)
- (void)frobbleAndBobble_so
{
if (![self conformsToProtocol:#protocol(SOManagedObject)]) return;
NSLog(#"%s: Thunderbirds are GO! Let's frobble and bobble!", __func__);
[self frobble_so];
[self bobble_so];
}
#end
You could optionally assert to ensure you are not sending the method to the wrong objects, or you could use respondsToSelector: instead of checking for protocol conformance. Whatever floats your boat, but this general tack should take you where you want to go.
I don't think it is possible. A similar question to this was answered earlier:
Defining categories for protocols in Objective-C?
Edit: I misread the question; I don't think it's possible to do what you're trying to do without messing with the Objective-C runtime. See Dave's comment below for why my answer is incorrect.
You should be able to do this if you swap the protocol and category notation like so:
#interface NSManagedObject (MyExtensionMethods) <SOManagedObject>
...
#end
Adam Sharp posted a solution that worked for me.
It involves 3 steps:
Defining the methods you want to add as #optional on a protocol.
Making the objects you want to extend conform to that protocol.
Copying those methods into those objects at runtime.
Check out the link for the full details.