Objective-C protocol as parameter in another protocol - objective-c

I am trying to create a generic repository (pattern) that accesses my web api. I am having trouble understanding how protocols work in objective-c (I come from c# where interfaces are a bit different).
What I am trying to do is have ProtocolA be a parameter in another ProtocolB and then in the implementation of ProtocolB access methods on ProtocolA, since the object passed in to ProtocolB must implement ProtocolA itself. Am I thinking about that correctly?
This is what I have thus far, but can't seem to get it to work - maybe my logic is wrong:
//PGenericModel.h
#protocol PGenericModel <NSObject>
- (void)testMethod;
#end
//PGenericRepository.h
#import "PGenericModel.h"
#protocol PGenericRepository <NSObject>
#required
- (void)Get:(id<PGenericModel>*)entity;
#end
//GenericRepository.m
#import "GenericRepository.h"
#implementation GenericRepository
- (void)Get:(id<PGenericModel>*)entity
{
//GET
[entity testMethod] <-- this doesn't work...
}
#end

It is not working because an id type is already a pointer to an Objective-c object.
So you should declare the signature as
- (void)Get:(id<PGenericModel>)entity
not id<PGenericModel>*, otherwise the argument would be a pointer to a pointer to an Objective-C object, you can't send messages to it unless you get the concrete value.

Related

Objective-C "Override" Specifier

In Java, C++11 and some other languages you can specify that a method is intended to override another method from a base class or interface, if you then at a later point remove the method from the base class you get a compiler error. I use protocols with optional methods a lot and find that if I remove a method from there I have a tendency to forget to remove the code that implemented the method. This does not generate an error or a warning, thus creating a "dead" method.
Consider:
#protocol Prot <NSObject>
#optional
- (void)bar;
- (void)tempBar;
#end
#interface MyType : NSObject <Prot>
#end
#implementation MyType
- (void)bar { /**/ }
- (void)tempBar { /**/ }
#end
If I at one point remove tempBar from the protocol, I would like to get at least a warning from tempBar being implemented in MyType.
Is there any way in Objective-C to specify that a method is expected to be an implementation of a protocol method?
Objective-C is a dynamic language and this is rather impossible to enforce at compile time. Note that in Obj-C you can actually call methods there are not even there and the app won't crash (well, the default implementation will raise an exception but you can change that behavior).
The method can be also added in an extension, or added at runtime. Or it is just not present in the header.
Note there is also the opposite problem. When subclassing, you can override a method which you don't even know is there, because it is not present in the headers.
This is one of the reasons why Apple is moving to a more predictable language, that is, Swift.

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

what does #class do in iOS 4 development?

Is there any difference in doing
#class MyViewController;
rather than doing the normal import of the .h into the appdelegate.h
#import "MyViewController.h"
I've seen some example recently that use the #class way and wondered if there any differences.
thanks.
There is a big difference.
#class MyViewController;
Is a forward declaration for the object MyViewController. It is used when you just need to tell the compiler about an object type but have no need to include the header file.
If however you need to create an object of this type and invoke methods on it, you will need to:
#import "MyViewController.h"
But normally this is done in the .m file.
An additional use of forward declarations is when you define a #protocol in the same header file as an object that uses it.
#protocol MyProtocolDelegate; //forward declaration
#interface MyObject {
id<MyProtocolDelegate> delegate;
...
}
...
#end
#protocol MyProtocolDelegate
... //protocol definition
#end
In the above example the compiler needs to know that the #protocol MyProtocolDelegate is valid before it can compile the MyObject object.
Simply moving the protocol definition above MyObject definition would also work.
#class allows you to declare that a symbol is an Objective-c class name without the need to #import the header file that defines the class.
You would use this where you only need the class name defined for the purposes of declaring a pointer to the class or a method parameter of the class, and you do not need to access any methods, fields, or properties in the class.
It saves a minuscule amount of compile time vs the #import, and it sometimes helps avoid messy include circularity issues.
[And, as rjstelling points out, it's sometimes useful where you have interleaved declarations and you need to "forward declare" something.]

Since when is it possible to declare Objective-C 2.0 properties in a category?

I always thought that one cannot declare an object property in a category.
Until my partner did it in our app's code, and it seemed to work.
I went on a SO and Google binge to try to explain to him that no, Objective-C categories can only be used to add methods, not properties. I found questions such as:
Setting New Property In Category Interface Implementation (look at the accepted answer)
Can I add a property for a method not in my category?
But then I found this link on Apple's site that contains the following about the #property declaration:
A property declaration begins with the
keyword #property. #property can
appear anywhere in the method
declaration list found in the
#interface of a class. #property can
also appear in the declaration of a
protocol or category. (emphasis added)
I know that this doesn't work:
#interface MyClass ()
NSInteger foobar;
- (void) someCategorizedMethod;
#end
But this compiles:
#interface MyClass ()
#property NSInteger foobar;
- (void) someCategorizedMethod;
#end
My question is (a) what's the best practice here? and (b) is this something that is new to Objective-C 2.0, and instead of using a "real" iVar, it simply uses associative storage behind the scenes to make this work?
You have always been able to declare an #property in a category. What you couldn't do -- and still can't -- is declare storage for the property in the category, neither as an instance variable nor via `#synthesize.
However....
#interface MyClass () is not a category. It is a class extension and has a distinctly more specific role than a category.
Namely, a class extension can be used to extend a class's #interface, and this includes #properties that can be #synthesized (including synthesizing storage in the modern runtime).
Foo.h:
#interface Foo
#end
Foo.m:
#interface Foo()
#property int x;
#end
#implementation Foo
#synthesize x; // synthesizes methods & storage
#end
it simply uses associative storage
behind the scenes to make this work?
Nope -- it is a real instance variable. The modern runtime fixes the fragile base class problem.
#interface MyClass ()
NSInteger foobar;
- (void) someCategorizedMethod;
#end
The above doesn't work (as expected) because foobar is, effectively, a global variable.
If you change it to:
#interface MyClass () {
NSInteger foobar;
}
- (void) someCategorizedMethod;
#end
Then it'll work with the latest release of the llvm compiler (with the right flags, as #Joshua indicated in a comment).
Generally speaking, properties are nothing different from other methods. As long as the ivar used is available in the ordinary class, there is no problem at all. It's just syntactic sugar.
Things start to get more difficult if also the ivar is automatically created, as is possible in some configurations.
The main point here is that declaration of the ivar is independent from the property.
Assotiative storage is the solution.
Have a look at this post.