Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to simulate protected properties and methods in objective-c [duplicate]

Possible Duplicate:
Protected methods in objective-c

The way to declare private properties is simple.

You declare that in extension that's declared in .m files.

Say I want to declare protected properties and access it from the class and subclass.

This is what I tried:

//
//  BGGoogleMap+protected.h
//
//

#import "BGGoogleMap.h"

@interface BGGoogleMap ()
@property (strong,nonatomic) NSString * protectedHello;
@end

That one is compile. Then I added:

#import "BGGoogleMap+protected.h"

@implementation BGGoogleMap ()

-(NSString *) protectedHello
{
    return _
}

@end

Problem starts. I can't implement class extension outside the original .m files it seems. Xcode will demand something inside that bracket.

If I do

#import "BGGoogleMap+protected.h"

@implementation BGGoogleMap (protected)

-(NSString *) protectedHello
{
    return _
}

@end

I cannot access the ivar of _protectedHello declared in BGGoogleMap+protected.h

Of course I can use regular category rather than extension, but that means I can't have protected properties.

So what should I do?

like image 200
user4234 Avatar asked Nov 30 '12 02:11

user4234


1 Answers

The Objective-C Programming Language says this:

Class extensions are like anonymous categories, except that the methods they declare must be implemented in the main @implementation block for the corresponding class.

So you could just implement your class extension's methods in the class's main @implementation. That is the simplest solution.

A more complicated solution is to declare your “protected” messages and properties in a category, and declare any instance variables for that category in a class extension. Here's the category:

BGGoogleMap+protected.h

#import "BGGoogleMap.h"

@interface BGGoogleMap (protected)

@property (nonatomic) NSString * protectedHello;

@end

Since a category cannot add an instance variable to hold protectedHello, we need a class extension also:

`BGGoogleMap_protectedInstanceVariables.h'

#import "BGGoogleMap.h"

@interface BGGoogleMap () {
    NSString *_protectedHello;
}
@end

We need to include the class extension in the main @implementation file so that the compiler will emit the instance variable in the .o file:

BGGoogleMap.m

#import "BGGoogleMap.h"
#import "BGGoogleMap_protectedInstanceVariables.h"

@implementation BGGoogleMap

...

And we need to include the class extension in the category @implementation file so that the category methods can access the instance variables. Since we declared the protectedHello property in a category, the compiler will not synthesize the setter and getter method. We have to write them by hand:

BGGoogleMap+protected.m

#import "BGGoogleMap+protected.h"

@implementation BGGoogleMap (protected)

- (void)setProtectedHello:(NSString *)newValue {
    _protectedHello = newValue; // assuming ARC
}

- (NSString *)protectedHello {
    return _protectedHello;
}

@end

Subclasses should import BGGoogleMap+protected.h to be able to use the protectedHello property. They should not import BGGoogleMap_protectedInstanceVariables.h because the instance variables should be treated as private to the base class. If you ship a static library without source code, and you want users of the library to be able to subclass BGGoogleMap, ship the BGGoogleMap.h and BGGoogleMap+protected.h headers, but don't ship the BGGoogleMap_protectedInstanceVariables.h header.

like image 88
rob mayoff Avatar answered Oct 25 '22 02:10

rob mayoff