Question

I have a base view controller that a number of other view controllers subclass. Is there a way of enforcing certain methods which have to be overridden in a subclass?

For safety sake more than anything.

Cheers

Was it helpful?

Solution 2

In other languages this is done using abstract classes and methods. In Objective-C there is no such thing.

The closest you can get is raising an exception in the superclass so subclasses are 'forced' to override them.

[NSException raise:NSInternalInconsistencyException format:@"Subclasses must override %@", NSStringFromSelector(_cmd)];

OTHER TIPS

In Xcode (using clang etc) I like to use __attribute__((unavailable(...))) to tag the abstract classes so you get an error/warning if you try and use it.

It provides some protection against accidentally using the method.

Example

In the base class @interface tag the "abstract" methods:

- (void)myAbstractMethod:(id)param1 __attribute__((unavailable("You should always override this")));

Taking this one-step further, I create a macro:

#define UnavailableMacro(msg) __attribute__((unavailable(msg)))

This lets you do this:

- (void)myAbstractMethod:(id)param1 UnavailableMacro("You should always override this");

Like I said, this is not real compiler protection but it's about as good as your going to get in a language that doesn't support abstract methods.

Inspired by rjstelling, I solved this in an even more satisfying way:

In your prefix, define:

#define abstract __attribute__((unavailable("abstract method")))

Then you can add abstract methods as follows:

- (void) getDataIdentifier abstract;

Trying to call this method will then result in compiler semantic issue/error (Xcode 5.1):

'getDataIdentifier' is unavailable: abstract method

Update: It does not seem to work to call the method (at least not from within the class hierarchy). I will come back with an update if I manage to fix this.

You can require subclasses to implement a property (for why not methods see below) at compile time by using an LLVM feature as follows:

NS_PROTOCOL_REQUIRES_EXPLICIT_IMPLEMENTATION
@protocol Protocol
@property (readonly) id theWorstOfTimes; // expected-note {{property declared here}} 
@end

// In this example, ClassA adopts the protocol.
@interface ClassA : NSObject <Protocol>
@property (readonly) id theWorstOfTimes;
@end

@implementation ClassA
- (id)theWorstOfTimes{
    return nil; // default implementation does nothing
}
@end

// This class subclasses ClassA (which also adopts 'Protocol').
@interface ClassB : ClassA <Protocol>
@end

@implementation ClassB // expected-warning {{property 'theWorstOfTimes' requires method 'theWorstOfTimes' to be defined - use @synthesize, @dynamic or provide a method implementation in this class implementation}} 
@end

As you can see when ClassB re-implements the protocol it shows the expected-warning that the property method is missing. NS_PROTOCOL_REQUIRES_EXPLICIT_IMPLEMENTATION is just a macro for __attribute__((objc_protocol_requires_explicit_implementation)) and this code sample is modified from the test harness of that feature here.

This used to work also for methods but a bug has been introduced in 2014 via a misunderstanding in what it is for and now it only works for properties, I have emailed the author to make them aware so hopefully it changed back to how it was. To test the bug you can add a method to the protocol and you will see there is no warning in ClassB. Hopefully you can change some of your methods to read only properties to at least get some use out of it.

Here is some documentation on NS_PROTOCOL_REQUIRES_EXPLICIT_IMPLEMENTATION: ImplementingAccessibilityforCustomControls nsaccessibilitybutton

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top