If I have an protocol (say UIPickerViewDataSource) and I implement its required methods, do I need to declare those methods in the header file of my class?
At the moment I'm not doing so and I get a warning of incomplete implementation (although everything works fine). If I do add the required methods in the then I don't get such warning:
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
Is this the correct behaviour? Is it really necessary to add the declaration for required protocol methods in the header file of my class?
No, you don't. Declaring that the class implements that protocol and implementing the methods is enough. You could still declare them in the header for documentation purposes, though.
The correct way is to declare that your class implements the protocol. If for instance your class is called LordSandwichViewController, then your class interface must look like this:
#interface LordSandwichViewController : UIViewController <UIPickerViewDataSource> {
{
}
So you don't declare the protocol methods in your class interface, only the protocol.
Incomplete implementation warnings tell you that you are not implementing all the required methods you are either:
Defining in your header.
Declaring a method required by a protocol you're conforming to.
Look at what methods it's expecting, and implement those.
Related
For example, I have such a protocol
public protocol MyProtocol
{
func foo()
}
Protocol implementation
class MyClass : MyProtocol
{
public func foo() {...}
}
there is no way to know if the method foo() is a (direct) class method or protocol implementation
So, sometimes (eg:) if a certain class implements few protocols where each of them has few methods it is hard to know which method related to which protocol.
So the question is - is there actually no way to know it?
UPD
I need to know it just for a better understanding of the code and in addition, it is easier to navigate when I know which method related to which protocol.
When you are writing code, it is usually a good idea to write implementations of protocol methods in their own separate extensions. For example:
class MyClass {
// implement methods unrelated to any protocols here
}
extension MyClass : Protocol1 {
// implement the methods in Protocol1
}
extension MyClass : Protocol2 {
// implement the methods in Protocol2
}
// etc
This way you know exactly what methods belong to which protocol.
However, let's say you are reading someone else's code that you can't change.
In Xcode, you can see if a method in a class implements a protocol by holding the command key and then clicking on its name, then the "quick actions" menu comes up:
If you click on "Jump to definition",
you will be taken to the method declaration in the protocol, if the method implements a method declared in a protocol, or
you will stay where you are, if it's just a regular old method
Do note that you will also stay where you are, if the method implements a protocol method, but is overridden. So if you see an overridden method, and wants to know if it is a requirement for a protocol or not, you'll have to go to the superclass first.
Or, use AppCode, where there are markers beside these methods:
The "I" markers with a red upwards arrow are what you're looking for. Clicking on them takes you to the declaration in the protocol. For overridden methods, they look no different from regular overridden methods, and you still need to go to the superclass first by clicking on the "O" marker with a red upwards arrow.
The only downside of this is of course, you need to pay for AppCode :(
I've never worked with objective C but have a fair bit of experience with C++.
What exactly is the difference between a superclass and a protocol in objective C? I read that a protocol is essentially a pure virtual class, but is that it? Is a protocol simply a specific type of superclass?
A protocol is a contract a class is going to conform to. When a class conforms to a protocol it tells the compiler that it will implement all the methods and all the properties declared in the protocol.
In Objective-C the class additionally needs a superclass. In a lot of cases this is NSObject. The superclass implements already a lot of methods (like isEqual:). A protocol never implements any methods or defines any property.
A protocol tells which properties/operations a class must implement. A superclass implements them and you can add your own stuff on top.
A protocol defines a set of method definitions that a class or struct must implement, very much like a Java interface.
A superclass is the class from which a given class inherits its method definitions, the implementation for those methods, and the instance and class properties.
Can I call a protocol method from a child on its super class, even though the super class supports the protocol privately?
Let's say I have a Class A which privately conforms to UIGestureRecognizerDelegate protocol. Class B inherits from Class A but when I tried to call [super gestureRecognizerShouldBegin:gestureRecognizer]; I get an error.
Any idea?
The UIScrollViewDelegate doesn't declare a method named gestureRecognizerShouldBegin:gestureRecognizer:.
But generally speaking, yes, its possible to call methods declared in protocols that the super class implements, but keep in mind that methods marked with #optional in the protocol aren't guaranteed to be implemented (you can check this via the respondsToSelector: method)
#interface ThreadsViewController : UIViewController <NSKeyValueObserving>
{
}
Error:Cannot find protocol declaration for 'NSKeyValueObserving'.
I'm using Foundation framework. Why do I have this error?
NSKeyValueObserving is an informal protocol:
An informal protocol is a category on NSObject, which implicitly makes almost all objects adopters of the protocol. (...) Implementation of the methods in an informal protocol is optional. Before invoking a method, the calling object checks to see whether the target object implements it.
You can not adopt an informal protocol using the angle brackets syntax, that is for formal protocols. With informal protocols, you simply implement the protocol methods. Your attempt to conform to the protocol NSKeyValueObserving in the #interface block:
#interface ThreadsViewController : UIViewController <NSKeyValueObserving>
is the reason why the compiler is complaining.
From Protocols:
Being informal, protocols declared in categories don’t receive much language support. There’s no type checking at compile time nor a check at runtime to see whether an object conforms to the protocol.
You should check the documentation for NSKeyValueObserving. In that you can find at top that in which framework resides. Just confirm that you are including that framework in your project.
Are you sure FoundationFramework is added to your project? If not, add it.
I have a class which is intended to be abstract. This means: When someone subclasses it, a few methods MUST be overwritten.
But on the other hand, those methods are not intended to be called manually from anywhere except inside the abstract class (the superclass of the subclass).
Must I declare these methods in .h anyways or can I just add comments in .h which say "you must overwrite -foo and -bar"? Or is there a better pattern to make abstract methods?
Related: Is there a way to create an abstract class in Objective C?
Objective-C doesn't actually have a way to declare a class as abstract. From Apple's Docs:
Abstract Classes
Some classes are designed only or
primarily so that other classes can
inherit from them. These abstract
classes group methods and instance
variables that can be used by a number
of different subclasses into a common
definition. The abstract class is
typically incomplete by itself, but
contains useful code that reduces the
implementation burden of its
subclasses. (Because abstract classes
must have subclasses to be useful,
they’re sometimes also called abstract
superclasses.)
Unlike some other languages,
Objective-C does not have syntax to
mark classes as abstract, nor does it
prevent you from creating an instance
of an abstract class.
The NSObject class is the canonical
example of an abstract class in Cocoa.
You never use instances of the
NSObject class in an application—it
wouldn’t be good for anything; it
would be a generic object with the
ability to do nothing in particular.
The NSView class, on the other hand,
provides an example of an abstract
class instances of which you might
occasionally use directly.
Abstract classes often contain code
that helps define the structure of an
application. When you create
subclasses of these classes, instances
of your new classes fit effortlessly
into the application structure and
work automatically with other objects.
So to answer your question, yes, you need to place the method signature in the header, and should implement the method in the base class such that it generates an error if called, like the related question's answer states.
You can also use a protocol to force classes to implement certain methods.
However you choose to implement the base class, clearly document in the header, as well as in your documentation, exactly what the class assumes and how to go about sub-classing it correctly.
Whenever possible write your code so that improper implementations fail to compile. If you cannot do that then you should try to generate a runtime error (at the very least in a debug build) if the subclass is not written correctly. Do not rely on comments because people will not read them.
You must declare your "protected" and "abstract" methods in a header file, but you can use separate categories to clearly indicate their purpose and intended use.
#interface MyBaseClass : NSObject {
}
- (void)foo;
#end
#interface MyBaseClass(ProtectedMethods)
- (void)bar;
#end
#interface MyBaseClass(AbstractMethods) // Subclasses must implement
- (void)internalBar;
#end
You can put everything in a single header, or you could put your protected and abstract declarations in a separate "protected" header, say MyClassProtected.h, meant to be included only by your subclass implementations. It depends on how badly you want "hide" your protected methods.
Your base class can log, assert, or throw when an abstract/pure-virtual method is called.
As other people have said, Objective-C does not support pure virtual classes.
You can enforce pure virtual behaviour at runtime though. The cleanest way to do this is by using the Objective-C runtime's _cmd and NSObject's -doesNotRecognizeSelector:
- (void)iMustBeImplementedInaSubclass;
{
[self doesNotRecognizeSelector:_cmd]; // Pure virtual
}
As ben says you are probably better served by using a protocol to get your API design right.