三.类
1.Dynamically Creating a Class
目标代码
@interface Product : NSObject
@property (readonly) NSString *name;
@property (readonly) double price;
- (instancetype)initWithName:(NSString *)name price:(double)price;
@end
@implementation Product
- (instancetype)initWithName:(NSString *)name
price:(double)price
{
self = [super init];
if(!self) {
return nil;
}
self.name = name;
self.price = price;
return self;
}
@end
runtime代码
Class c = objc_allocateClassPair([NSObject class], "Product", 0);
class_addIvar(c, "name", sizeof(id), log2(sizeof(id)), @encode(id));
class_addIvar(c, "price", sizeof(double), sizeof(double), @encode(double));
Ivar nameIvar = class_getInstanceVariable(c, "name");
ptrdiff_t priceIvarOffset = ivar_getOffset(class_getInstanceVariable(c, "price"));
IMP initIMP = imp_implementationWithBlock( ^(id self, NSString *name, double price) {
object_setIvar(self, nameIvar, name);
char *ptr = ((char *)(__bridge void *)self) + priceIvarOffset;
//void *memcpy(void*dest, const void *src, size_t n);
//由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。
memcpy(ptr, &price, sizeof(price));
return self;
});
const char *initTypes = [[NSString stringWithFormat:@"%s%s%s%s%s%s", @encode(id),@encode(id), @encode(SEL), @encode(id), @encode(id), @encode(NSUInteger)] UTF8String];
class_addMethod(c, @selector(initWithFirstName:lastName:age:),initIMP, initTypes);
IMP nameIMP = imp_implementationWithBlock(^(id self) {
return object_getIvar(self, nameIvar);
});
const char *nameTypes = [[NSString stringWithFormat:@"%s%s%s",@encode(id), @encode(id), @encode(SEL)] UTF8String];
class_addMethod(c, @selector(name), nameIMP, nameTypes);
IMP priceIMP = imp_implementationWithBlock(^(id self) {
char *ptr = ((char *)(__bridge void *)self) + priceIvarOffset;
double price;
memcpy(&price, ptr, sizeof(price));
return price;
});
const char *priceTypes = [[NSString stringWithFormat:@"%s%s%s", @encode(double), @encode(id), @encode(SEL)] UTF8String];
class_addMethod(c, @selector(age), priceIMP, priceTypes); objc_registerClassPair(c);
执行
Product *widget = [[Product alloc] initWithName:@"Widget" price:50.00];
NSLog(@"%@: %g", widget.name, widget.price);













网友评论