7

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?

Community
  • 1
  • 1
user4234
  • 1,523
  • 1
  • 20
  • 37
  • 1
    Rob wrote an awesome answer not available on the other question. Also this question is about simulation rather than actual protected variable, which is impossible to implement in objective-c – user4234 Dec 03 '12 at 09:37

3 Answers3

7

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.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • Rob, I think BGGoogleMap+protected.h alone will generate compile error. Did you try this? Also, an answer here seems to work. http://stackoverflow.com/questions/3725857/protected-methods-in-objective-c it's awkward due to using protocol too. – user4234 Dec 03 '12 at 08:36
  • No the answer over there doesn't involve properties at all and no wonder get only 2 upvotes. – user4234 Dec 03 '12 at 08:38
  • Hmm. Maybe you're correct. I'll check. – user4234 Dec 03 '12 at 08:40
  • I'm not sure what you're asking about. If you're getting a compile error, copy the error message and post it. – rob mayoff Dec 03 '12 at 08:44
  • I am not sure we can declare @property in category, which was the whole problem. However, then I realized that you take care of that by declaring the iVar in extension. – user4234 Dec 03 '12 at 09:29
  • Now here is the issue, you declare BGGoogleMap_protectedInstanceVariables.h. That means all other ivar and private properties will be in BGGoogleMap_protectedInstanceVariables.h too right? Including those who I don't plan to share with my subclasses. Not like we can create 2 extensions can we? – user4234 Dec 03 '12 at 09:34
  • "@property defines an interface, not an implementation. In your case, you're defining a readwrite property. This means that you're promising to implement -myObject and -setMyObject:. This has nothing to do with ivars." See http://stackoverflow.com/questions/9065417/objective-c-interface-declaring-variable-vs-just-property – mmvie Dec 03 '12 at 09:45
  • Quite clever, thank you! – Ege Akpinar Dec 29 '15 at 18:11
2

I wish I could tell you otherwise but you just can't. See this question for more information: Protected methods in Objective-C.

Community
  • 1
  • 1
mmvie
  • 2,571
  • 7
  • 24
  • 39
0

I am not sure, what you want to do? Something Hacking or Cracking of Data Abstraction out of OOPS concept?

Extensions are used to add properties. You have successfully added private property as in

#import "BGGoogleMap.h"

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

What are you doing in this ?

#import "BGGoogleMap+protected.h"

@implementation BGGoogleMap ()

-(NSString *) protectedHello
{
    return _
}

@end

You have extended a class, now you are again implementing same class !!! Twice!!! And category only comes with .h file. I guess you are creating yourself a .m file, that not acceptable.

Private properties cant be accessed outside the class, it can be accessed only from the base class or subclass. That is what the error is.

I can't implement class extension outside the original .m files it seems. 

Yes this is abstraction and data hiding of Objective-c !!!

Anoop Vaidya
  • 46,283
  • 15
  • 111
  • 140
  • "Private properties cant be accessed outside the class, it can be accessed only from the base class or subclass." Don't know about properties, but this is not true for methods, which is what he wants... – mmvie Dec 03 '12 at 09:47
  • He is using properties... kindly check to access the property he tried to override it by making setters and getters. So his main idea was wrong, thats why his question is closed. – Anoop Vaidya Dec 03 '12 at 09:51