Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Categories in Objective-C aren't working

I'm developing an iOS application that needs to deploy to iOS 3.1.3. I need to extend some of the functionality of the NSData class and am using the following code inside NSData+Base64 (truncated to show the interesting part):

NSData+Base64.h

[...]

@interface NSData (Base64)

+ (NSData *)dataFromBase64String:(NSString *)aString;
- (NSString *)base64EncodedString;

@end

NSData+Base64.m

@implementation NSData (Base64)

[...]

//
// base64EncodedString
//
// Creates an NSString object that contains the base 64 encoding of the
// receiver's data. Lines are broken at 64 characters long.
//
// returns an autoreleased NSString being the base 64 representation of the
//  receiver.
//
- (NSString *)base64EncodedString
{
    size_t outputLength;
    char *outputBuffer =
        NewBase64Encode([self bytes], [self length], true, &outputLength);
    
    NSString *result =
        [[[NSString alloc]
            initWithBytes:outputBuffer
            length:outputLength
            encoding:NSASCIIStringEncoding]
        autorelease];
    free(outputBuffer);
    return result;
}

@end

However, when I try to message this selector:

NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
NSString *hash = [HMAC base64EncodedString];

I get the following error:

 -[NSConcreteData base64EncodedString]: unrecognized selector sent to instance 0x6146e70
2010-11-09 13:44:41.443 SpringboardApplication[21318:40b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteData base64EncodedString]: unrecognized selector sent to instance 0x6146e70'

I read a lot about iOS 3.1.x having problems with categories. I tried adding the flags -all_load and -ObjC (both separately and together) to no avail. I would really appreciate some direction of how to get this selector to work.

Thanks!

like image 887
Daniel Avatar asked Nov 09 '10 20:11

Daniel


People also ask

How do you add a category in Objective-C?

Making a Category is simple.Add a new file to the project. Choose Objective-C file. (At the bottom of the page it states “An empty Objective-C file, category, protocol, or extension.” This is the one you want.)

What can category in Objective-C do?

A category can be declared for any class, even if you don't have the original implementation source code. Any methods that you declare in a category will be available to all instances of the original class, as well as any subclasses of the original class.

What does @() mean in Objective-C?

In Objective-C, any character , numeric or boolean literal prefixed with the '@' character will evaluate to a pointer to an NSNumber object (In this case), initialized with that value. C's type suffixes may be used to control the size of numeric literals. '@' is used a lot in the objective-C world.

What is the difference between category and extension in Objective-C?

Category and extension both are basically made to handle large code base, but category is a way to extend class API in multiple source files while extension is a way to add required methods outside the main interface file.


1 Answers

It really seems like your category isn't being compiled or linked into the same target that you're using it from. You should make sure that NSData+Base64.m is marked to be compiled by the same target that it's being used from by getting info on the two files and comparing the targets they're assigned to.

A test you can perform is to add a line with an #error error message to NSData+Base64.m, which will cause the build to fail when it gets to that file. Like this:

#error We're now compiling NSData+Base64.m

Then look and see which target fails to compile.

like image 104
Ryan Avatar answered Oct 05 '22 21:10

Ryan