Категории в Objective-C не работают

Я разрабатываю приложение iOS, которое необходимо развернуть в iOS 3.1.3. Мне нужно расширить некоторые функции класса NSData, и я использую следующий код внутри NSData + Base64 (усеченный, чтобы показать интересную часть):

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 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

Однако, когда я пытаюсь передать этот селектор:

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

Я получаю следующую ошибку:

 -[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'

Я много читал о iOS 3.1.x, имеющем проблемы с категориями. Я попытался добавить флаги -all_load и -ObjC (как отдельно, так и вместе) безрезультатно. Я бы очень признателен за то, как заставить этот селектор работать.

Спасибо!

Ответ 1

Кажется, что ваша категория не скомпилирована или не связана с той же целью, с которой вы ее используете. Вы должны убедиться, что NSData + Base64.m помечен для компиляции той же целью, из которой он используется, путем получения информации о двух файлах и сравнения целей, к которым они привязаны.

Тест, который вы можете выполнить, - это добавить строку с сообщением об ошибке #error в NSData + Base64.m, что приведет к сбою сборки при ее получении. Вот так:

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

Затем посмотрите и посмотрите, какая цель не скомпилирована.

Ответ 2

У меня была такая же проблема с проектом ARC, который связывался с модулем без ARC, имеющим расширение категории.

Исправлена ​​ошибка с добавлением "Другие флаги компоновщика: -all_load" в родительском проекте ARC.

Ответ 3

Вы #import отредактировали заголовочный файл для своей категории? Я знаю, это звучит просто, но я забываю почти каждый раз.

Ответ 4

В "Углеродный излучатель" есть отличная статья об обработке категорий в iOS. Он описывает простой способ обработки импортируемых категорий в ваш проект.

Создайте файл, содержащий все импортируемые категории, в этом примере это Extensions.h:

#import "NSDate+Formatting.h"
#import "UIFonts+MyFonts.h"
#import "UIViewController+Tourbot.h"

Добавьте импортировать свой файл в AppName-Prefix.pch:

#import <Availability.h>

#ifndef __IPHONE_3_0
#warning "This project uses features only available in iPhone SDK 3.0 and later."
#endif

#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#import <CoreText/CoreText.h>
#import "Extensions.h" // Add import here
#endif

Ответ 5

В моем случае, когда я получил эту ошибку, я просто добавил файл .m в ресурсы Compiled, и он работает. Этого можно достичь, выбрав целевой проект- > Build Phases- > Compile Sources. Затем вы нажимаете на кнопку + слева внизу. В этом случае вы можете добавить файл NSData + Base64.m в источники компиляции. Затем вы очищаете свой проект и запускаете его. Думаю, это может помочь.