Private methods in a Category, using an anonymous category
Asked Answered
P

4

7

I'm creating a category over NSDate. It has some utility methods, that shouldn't be part of the public interface.

How can I make them private?

I tend to use the "anonymous category" trick when creating private methods in a class:

@interface Foo()
@property(readwrite, copy) NSString *bar;
- (void) superSecretInternalSaucing;
@end

@implementation Foo
@synthesize bar;
.... must implement the two methods or compiler will warn ....
@end

but it doesn't seem to work inside another Category:

@interface NSDate_Comparing() // This won't work at all
@end

@implementation NSDate (NSDate_Comparing)

@end

What's the best way to have private methods in a Category?

Permanganate answered 25/6, 2011 at 15:10 Comment(1)
An "anonymous category" is actually called a "Class Extension". The major difference between a class extension and a category is that the @implementation of the class extension must be in the primary @implementation block of the class.Heidt
P
4

It should be like this:

@interface NSDate ()

@end

@implementation NSDate (NSDate_Comparing)

@end
Promptitude answered 25/8, 2011 at 9:11 Comment(1)
In this case it shows a warning "Category is implementing a method which will also be implemented by its primary class".Jittery
P
2

It should be

@interface NSDate (NSDate_Comparing)

as in the @implementation. Whether or not you put the @interface in its own .h file is up to you, but most of the time you'd like to do this - as you want to reuse that category in several other classes/files.

Make sure to prefix your own methods to not interfere with existing method. or possible future enhancements.

Pyrargyrite answered 25/6, 2011 at 15:20 Comment(5)
I get a warning complaining about: "Semantic Issue: Duplicate definition of category 'NSDate_Comparing' on interface 'NSDate'"Permanganate
Do you include it multiple times? Or maybe there already exists that category (try a different name)?Pyrargyrite
I think @Fernando is putting two @interface blocks: one in the header file for the public methods and another one at the top of the implementation file intended for the "private" methods and this is causing the duplicate definition.Capet
Yes, exactly. That works fine with classes, is there a way to do it with Categories too?Permanganate
@Fernando Not including the "private" methods in the interface block and implementing them in the implementation block (above any calls to them) is not good enough? You could also declare them in a second category on NSDate, e.g. @interface NSDate(NSDateComparingPrivate) which would not be exposed as part of your API.Capet
F
2

I think the best way is to make another category in .m file. Example below:

APIClient+SignupInit.h

@interface APIClient (SignupInit)

- (void)methodIAddedAsACategory;
@end

and then in APIClient+SignupInit.m

@interface APIClient (SignupInit_Internal)
- (NSMutableURLRequest*)createRequestForMyMethod;
@end

@implementation APIClient (SignupInit)

- (void)methodIAddedAsACategory
{
    //category method impl goes here
}
@end

@implementation APIClient (SignupInit_Internal)
- (NSMutableURLRequest*)createRequestForMyMethod
{
    //private/helper method impl goes here
}

@end
Future answered 30/9, 2013 at 8:59 Comment(1)
I just tried this, and it doesn't work. Idk if it is because you didn't provide all code or something. Did you import anything special in the .m file?Slipover
T
-1

To avoid the warnings that the other proposed solutions have, you can just define the function but not declare it:

@interface NSSomeClass (someCategory) 
- (someType)someFunction;
@end

@implementation NSSomeClass (someCategory)

- (someType)someFunction
{
    return something + [self privateFunction];
}

#pragma mark Private

- (someType)privateFunction
{
    return someValue;
}

@end
Tuft answered 11/3, 2015 at 20:38 Comment(1)
I think the OP asking this question because your solution doesn't work. When you have a Category class and have a method that is not declared in the .h file, you can't use it in the .m file. Why don't you try it because I just tried it, and it doesnt work.Slipover

© 2022 - 2024 — McMap. All rights reserved.