5

I'm new to objective-C, so apologies if this is repeated somewhere. I have a category(?) that is something like:

inside SomeClass.h:

@interface SomeClass (SomeCategory) <SomeDelegate>
@property (nonatomic, retain) id somePublicProperty;
@property (nonatomic, retain) id someProperty; // <-- i want to move this to "private"
@end

and now in my SomeClass.m, all i have is:

@implementation SomeClass (SomeCategory)

// dynamic setters/getters here for someProperty.

@end

I think the someProperty is public. how do i make this "private"? (in other words, how do i syntactically put this in the .m file? i tried to use

@interface SomeClass (SomeCategory) {
    @property (nonatomic, retain) somePrivateProperty;
} 
@end

but it just complains that i have duplicate definition of the category. how do i do this correctly?

David T.
  • 22,301
  • 23
  • 71
  • 123

3 Answers3

8

In your .h file, you should not give the category. Just use:

@interface SomeClass : SomeBaseClass < SomeDelegate>
    @property (nonatomic, retain) id somePublicProperty;
@end

In your .m file, define your private property inside a class extension:

@interface SomeClass ()
    @property (nonatomic, retain) id somePrivateProperty;
@end

A class extension is not a like category in that it allows you to extend an interface as well as add new storage to your class.

In a class category, you can define new properties, but no storage will be allocated for it, so you have to do it by hand:

@interface SomeClass (SomeBaseCategory)
    @property (nonatomic, retain) id somePrivateProperty;
@end

@implementation SomeClass {
    id _somePrivateProperty;
}

    - (void)setSomePrivateProperty:(id)property {

        _somePrivateProperty = property;
    }

    - (id)somePrivateProperty {
         return _somePrivateProperty;
    }

@end

Otherwise your app will crash.

In any case, keep in mind that given the dynamic nature of Objective-C, your property will never be fully private, since you can always send a message to an Objective-C object through objc_msgsend and thus set or read the property value.

EDIT:

If you do not have the source code for a class implementation, you cannot define a class extension (as per source linked above).

In this case, you could use object association to define properties.

Community
  • 1
  • 1
sergio
  • 68,819
  • 11
  • 102
  • 123
  • This will not make the property private though. If you want a private property, a category in the m file is the way to go – Daniel Shteremberg Aug 25 '14 at 20:09
  • hmm... so in my code, the `SomeClass` is `UIWindow`. and whenever i try to do what you suggested, i get a "Duplicate interface definition for class `UIWindow`". how do i avoid this? – David T. Aug 25 '14 at 20:37
  • 2
    You can't create a class extension for a class for which you do not have the source code. This is also stated in the doc I linked. Check my edit for an alternative approach. – sergio Aug 25 '14 at 20:41
  • ahh. makes sense. thnx +1 – David T. Aug 25 '14 at 21:47
2

Just add the category definition in the .m file OUTSIDE the implementation block

Like so:

@interface MyClass (MyCategory)
@property (assign) BOOL myPrivateProperty;
@end

@implementation MyClass
...
@end
  • 1
    Sergio, you are right. I've made the edit so that it is a category. It looks like David just wants a private property though... so it really doesn't matter if it is a class extension or named category as long as it is in the m file – Daniel Shteremberg Aug 25 '14 at 20:12
  • I tried this already, but i get a warning: "Duplicate definition of category `SomeCategory` on interface `SomeClass`". how do i avoid this? – David T. Aug 25 '14 at 20:35
  • 1
    @DavidT. just use a different category name — like `SomeCategoryUnpublished`. The names aren't used for anything else anyway. – Tommy Aug 25 '14 at 21:39
  • That isn't a class extension. It is a category; a class extension would be `@interface MyClass ()`. – bbum Aug 25 '14 at 22:27
0

Categories are best used for adding capability to code you do not own and cannot change. Adding properties via categories is not impossible, but is much more difficult.

Class Extensions are best used for keeping properties your object needs, but are not intended to be public.

If you do truly need to add properties to this object, the way to do it is with the Objective-C runtime's associated objects

There's an excellent writeup of when/how to use them here

Jeff Holliday
  • 760
  • 6
  • 7