Определение классов выполнения Objective-C - PullRequest
4 голосов
/ 19 декабря 2011

Можно ли определить классы во время выполнения в target-c?
Например, я получаю файл XML, который определяет объект, создает его и использует его во время выполнения?

Ответы [ 3 ]

6 голосов
/ 19 декабря 2011

Да, посмотрите этот фрагмент кода, я создал здесь класс, используя только методы C и одно определение протокола (для простоты при вызове сообщений) ...

MyCObject.h

#import <Foundation/Foundation.h>

@protocol MyCObj_methods<NSObject>

-(NSString *) getString;
-(int) getInt;
+(NSString *) someStaticMethod;

@end

typedef id<MyCObj_methods> MyCObj;
extern Class MyCObj_class;

__attribute__((constructor))
void MyCObj_initialize();

MyCObj MyCObj_alloc(        id self,     SEL _cmd );
MyCObj MyCObj_new(          id self,     SEL _cmd );

NSString *MyCObj_someStaticMethod ( id self, SEL _cmd );

MyCObj MyCObj_init(         MyCObj self, SEL _cmd );
NSString *MyCObj_getString( MyCObj self, SEL _cmd );
int MyCObj_getInt(          MyCObj self, SEL _cmd );

MyCObject.m

#import "MyCObject.h"
#import <objc/Object.h>
#import <objc/runtime.h>

static Class myStaticClass;
Class MyCObj_class;

typedef struct
{
    Class isa;
    NSString *myString;
    int myInt;
} MyCObj_t;

void MyCObj_initialize(void);

__attribute__((constructor))
void MyCObj_initialize()
{
    MyCObj_class = objc_allocateClassPair([NSObject class], "MyCObj", 0);
    objc_registerClassPair(MyCObj_class);

    myStaticClass = object_getClass(MyCObj_class);

    class_addMethod(MyCObj_class, @selector(init),      (IMP)MyCObj_init,        "@@:");
    class_addMethod(MyCObj_class, @selector(getString), (IMP)MyCObj_getString,   "@@:");
    class_addMethod(MyCObj_class, @selector(getInt),    (IMP)MyCObj_getInt,      "i@:");

    class_addMethod(myStaticClass, @selector(alloc),            (IMP)MyCObj_alloc, "@@:");
    class_addMethod(myStaticClass, @selector(new),              (IMP)MyCObj_new,   "@@:");
    class_addMethod(myStaticClass, @selector(someStaticMethod), (IMP)MyCObj_someStaticMethod, "@@:");
}

MyCObj MyCObj_alloc(id self, SEL _cmd)
{
    return (MyCObj) class_createInstance(MyCObj_class, sizeof(MyCObj_t) - sizeof(Class));
}

MyCObj MyCObj_new(id self, SEL _cmd)
{
    return (MyCObj) [[MyCObj_class alloc] init];
}

NSString *MyCObj_someStaticMethod(id self, SEL _cmd)
{
    return @"Some Static Method";
}

MyCObj MyCObj_init(MyCObj self, SEL _cmd)
{
    struct objc_super super = { .receiver = self, .super_class = [NSObject class] };

    if ((self = (MyCObj) objc_msgSendSuper(&super, _cmd)))
    {
        ((MyCObj_t *) self)->myString = @"hello world!";
        ((MyCObj_t *) self)->myInt = 15;
    }

    return self;
}

NSString *MyCObj_getString(MyCObj self, SEL _cmd)
{
    return ((MyCObj_t *) self)->myString;
}

int MyCObj_getInt(MyCObj self, SEL _cmd)
{
    return ((MyCObj_t *) self)->myInt;
}

Использование:

MyCObj obj = [MyCObj_class new];
NSLog(@"%@ %i %@", [obj getString], [obj getInt], [MyCObj_class someStaticMethod]);
5 голосов
/ 19 декабря 2011

Да; вполне возможно. Подробности см. В Руководстве по программированию Objective-C (включая соответствующие руководства и документы).

Как сказал Джастин, идти по этому пути крайне нетипично. Если вы загружаете данные XML, это почти всегда приведение к тому, что XML должен иметь четко определенную структуру - строгую DTD или схему - и, таким образом, вам будет намного лучше с дисциплинированной, четко определенной моделью данных. скомпилировано в ваше приложение (через Core Data или прямую реализацию), к которому вы загружаете XML. Это позволяет более тщательно проверять и будет значительно проще.

Святой Грааль «потребления данных в свободной форме» часто заманчив, но на этом пути лежит безумие и множество рассказов о горе.

2 голосов
/ 19 декабря 2011

да, вы можете использовать среду выполнения objc для создания типа, определения методов и его хранения - и все это во время выполнения ... однако это очень необычно.

используемые вами интерфейсы находятся в заголовках среды выполнения objc/runtime.h, и вы хотите, чтобы вы вызывали objc_allocateClassPair, class_addMethod, class_addIvar и т. Д. Очевидно, что для создания класс и его расположение, селекторы и тому подобное из описания XML. Поэтому да, это возможно, но это не бесплатно.

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