Как вызвать методы в классе, который я создал динамически с помощью NSClassFromString? - PullRequest
3 голосов
/ 06 февраля 2011

Причина, по которой я выполняю динамическую загрузку классов, заключается в том, что я создаю один набор файлов, которые можно использовать в нескольких похожих проектах, поэтому выполнение #import и затем обычного создания экземпляра просто не будет работать.Динамические классы позволяют мне делать это, пока я могу вызывать методы в этих классах.Каждый проект имеет это в pch с другим именем "kMediaClassName", поэтому я могу динамически загружать разные классы в зависимости от проекта, в котором я нахожусь:

#define kMediaClassName @"Movie"

Вот код, который я использую для получения экземпляракласса динамически:

Class mediaClass = NSClassFromString(kMediaClassName);
id mediaObject = [[[mediaClass alloc] init] autorelease];

Затем я пытаюсь вызвать метод внутри этого динамического класса:

[mediaObject doSomething];

Когда я затем набираю это в Xcode, компилятор показывает предупреждение, чтоУ класса нет этого метода, хотя он и есть.Я вижу это прямо в моем файле Movie.h.Что здесь происходит?Как вызвать метод из динамически создаваемого класса?

А что, если мне нужно передать несколько аргументов?

[mediaObject loadMedia:oneObject moveThe:YES moveA:NO];

Заранее спасибо за помощь.

Ответы [ 4 ]

8 голосов
/ 06 февраля 2011

вы можете объявить протокол следующим образом:

@protocol MONMediaProtocol

/*
  remember: when synthesizing the class, you may want
  to add the protocol to the synthesized class for your sanity
*/

- (BOOL)downloadMediaAtURL:(NSURL *)url toPath:(NSString *)path loadIfSuccessful:(BOOL)loadIfSuccessful;

/* ...the interface continues... */

@end

используется:

Class mediaClass = NSClassFromString(kMediaClassName);
assert(mediaClass);

id<MONMediaProtocol> mediaObject = [[[mediaClass alloc] init] autorelease];
assert(mediaObject);

NSURL * url = /* expr */;
NSString * path = /* expr */;

BOOL loadIfSuccessful = YES;

BOOL success = [mediaObject downloadMediaAtURL:url toPath:path loadIfSuccessful:loadIfSuccessful];
2 голосов
/ 06 февраля 2011

Ну, это может быть там, но компилятор не знает об этом, потому что предполагает, что mediaClass - это просто некоторый объект Class, но ничего конкретного. NSClassFromString () является функцией времени выполнения и поэтому не может дать компилятору подсказку во время компиляции об объекте.

Что вы можете сделать:

  • Игнорировать предупреждение
  • Использование [media performSelector:@selector(doSomething)];

И, кстати, это неправильно:

Class mediaClass; = NSClassFromString(kMediaClassName);

должно быть:

Class mediaClass = NSClassFromString(kMediaClassName);
1 голос
/ 06 февраля 2011

более простое и интересное решение , чем NSInvocation:)

Class mediaClass = NSClassFromString(kMediaClassName);
if(mediaClass){
    id mediaObject = class_createInstance(mediaClass,0);
    objc_msgSend(mediaObject, @selector(doSomethingWith:andWith:alsoWith:), firstP, secondP,thirdP);
}

Пояснение:

class_createInstance(mediaClass,0); делает то же самое, что и [[mediaClass alloc] init]; если вам нужно автоматически выпустить его, просто сделайте обычный [mediaObject autorelease];

objc_msgSend() делает то же самое, что и метод performSelector:, но objc_msgSend() позволяет вам указать столько параметров, сколько вы хотите. Так что проще, чем NSInvocation верно? Кстати, их подпись:

id class_createInstance(Class cls, size_t extraBytes)
id objc_msgSend(id theReceiver, SEL theSelector, ...)

Для получения дополнительной информации вы можете обратиться к Objective-C Runtime Reference

0 голосов
/ 06 февраля 2011

Как говорит Джо Блоу, NSInvocation поможет вам в этом, хотя у NSObject есть несколько быстрых методов, которые вы можете использовать: -performSelector:, -performSelector:withObject: и -performSelector:withObject:withObject:.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...