Protected methods in Objective-C

Objective C

Objective C Problem Overview


What is the equivalent to protected methods in Objective-C? I want to define methods which only the derived classes may call/implement.

Objective C Solutions


Solution 1 - Objective C

You can simulate protected and private access to methods by doing the following:

  • Declare your private methods in a class extension (i.e. a unnamed category declared near the top of the class' .m file)
  • Declare your protected methods in a Subclass header – Apple uses this pattern with respect to UIGestureRecognizer (see documentation and reference to UIGestureRecognizerSubclass.h)

These protections are not, as Sachin noted, enforced at runtime (as they are in Java, for example).

Solution 2 - Objective C

> You can neither declare a method protected or private. Objective-C's dynamic nature makes it impossible to implement access controls for methods. (You could do it by heavily modifying the compiler or runtime, at a severe speed penalty, but for obvious reasons this is not done.)

Taken from Source.

Solution 3 - Objective C

Here is what I did to get protected methods visible to my subclasses, without requiring them to implement the methods themselves. This meant I didn't get compiler warnings in my subclass about having an incomplete implementation.

SuperClassProtectedMethods.h (protocol file):

@protocol SuperClassProtectedMethods <NSObject>
- (void) protectMethod:(NSObject *)foo;
@end

@interface SuperClass (ProtectedMethods) < SuperClassProtectedMethods >
@end

SuperClass.m: (compiler will now force you to add protected methods)

#import "SuperClassProtectedMethods.h"
@implementation SuperClass
- (void) protectedMethod:(NSObject *)foo {}
@end

SubClass.m:

#import "SuperClassProtectedMethods.h"
// Subclass can now call the protected methods, but no external classes importing .h files will be able to see the protected methods.

Solution 4 - Objective C

I just discovered this and it works for me.To improve upon Adam's answer, in your superclass make an implementation of the protected method in .m file but don't declare it in .h file. In your subclass make a new category in your .m file with the declaration of the protected method of the superclass and you can use the protected method of the superclass in your subclass. This will not ultimately prevent the caller of the supposedly protected method if forced at runtime.

/////// SuperClass.h
@interface SuperClass

@end

/////// SuperClass.m
@implementation SuperClass
- (void) protectedMethod
{}
@end

/////// SubClass.h
@interface SubClass : SuperClass
@end

/////// SubClass.m
@interface SubClass (Protected)
- (void) protectedMethod ;
@end

@implementation SubClass
- (void) callerOfProtectedMethod
{
  [self protectedMethod] ; // this will not generate warning
} 
@end

Solution 5 - Objective C

Another way using @protected variables.

@interface SuperClass:NSObject{
  @protected
    SEL protectedMehodSelector;
}

- (void) hackIt;
@end

@implementation SuperClass

-(id)init{

self = [super init];
if(self) {
 protectedMethodSelector = @selector(baseHandling);
 }

return self;
}

- (void) baseHandling {

  // execute your code here
}

-(void) hackIt {

  [self performSelector: protectedMethodSelector];
}

@end

@interface SubClass:SuperClass
@end

@implementation SubClass

-(id)init{

self = [super init];
if(self) {
 protectedMethodSelector = @selector(customHandling);
 }

return self;
}

- (void) customHandling {

  // execute your custom code here
}

@end

Solution 6 - Objective C

You can define the method as a private method of the parent class and can use [super performSelector:@selector(privateMethod)]; in the child class.

Solution 7 - Objective C

One option is to use class extension to hide methods.

In .h:

@interface SomeAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

In .m:

@interface SomeAppDelegate()
- (void)localMethod;
@end

@implementation SomeAppDelegate

- (void)localMethod
{
}

@end

Solution 8 - Objective C

You can sort of do this with a category.

@interface SomeClass (Protected)
-(void)doMadProtectedThings;
@end

@implementation SomeClass (Protected)

- (void)doMadProtectedThings{
    NSLog(@"As long as the .h isn't imported into a class of completely different family, these methods will never be seen. You have to import this header into the subclasses of the super instance though.");
}

@end

The methods aren't hidden if you import the category in another class, but you just don't. Due to the dynamic nature of Objective-C it's actually impossible to completely hide a method regardless of a calling instance type.

The best way to go is probably the class continuation category as answered by @Brian Westphal but you'll have to redefine the method in this category for each subclassed instance.

Solution 9 - Objective C

I usually name protected method with internal prefix:

-(void) internalMethod;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLK.View Question on Stackoverflow
Solution 1 - Objective CBrian WestphalView Answer on Stackoverflow
Solution 2 - Objective CSachin ShanbhagView Answer on Stackoverflow
Solution 3 - Objective CMichael KernahanView Answer on Stackoverflow
Solution 4 - Objective CredwudView Answer on Stackoverflow
Solution 5 - Objective Cmarius bardanView Answer on Stackoverflow
Solution 6 - Objective CchinthakadView Answer on Stackoverflow
Solution 7 - Objective CohhoView Answer on Stackoverflow
Solution 8 - Objective CAdam WaiteView Answer on Stackoverflow
Solution 9 - Objective ClbsweekView Answer on Stackoverflow