首先,我完全@zpasternack說,「延遲加載」不應被濫用同意。但是,使用Objective-C運行時的功能完全可以自動生成setter和getter。實際上,CoreData
正在這樣做。
無論如何,我都拿出了一些愚蠢的代碼實現了一個名爲LazyClass
類,您可以在其中像lazyArray
聲明動態特性(見下文)。使用動態方法分辨率,當屬性首次被訪問時,調用相應類的默認+alloc
和-init
方法的getter將被自動添加到類中。所有基礎實例變量都存儲在名爲myVars
的NSMutableDictionary
中。當然你也可以通過運行時API來操作ivars,但是使用字典應該可以節省一些工作。
請注意,這只是實現顯示它是如何工作的基本思路。它缺乏錯誤檢查,不應該被運送。
LazyClass.h
@interface LazyClass : NSObject
@property NSMutableDictionary *myVars;
// lazily initialized property
@property NSArray *lazyArray;
@end
LazyClass。米
#import "LazyClass.h"
#import <objc/objc-runtime.h>
@implementation LazyClass
@dynamic lazyArray;
- (instancetype)init {
self = [super init];
self.myVars = [NSMutableDictionary dictionary];
return self;
}
- (NSMutableDictionary *)getMyVars {
return self.myVars;
}
// the generated getter method
id dynamicGetterMethodIMP(id self, SEL _cmd) {
// selector name, which is also the property name
const char *selName = sel_getName(_cmd);
NSString *selNSName = [NSString stringWithCString:selName encoding:NSUTF8StringEncoding];
NSString *keyPath = [NSString stringWithFormat:@"myVars.%@", selNSName];
if (![self valueForKeyPath:keyPath]) {
// get the actual type of the property
objc_property_t property = class_getProperty([self class], selName);
const char *attr = property_getAttributes(property);
NSString *attrString = [[NSString alloc] initWithCString:attr encoding:NSUTF8StringEncoding];
NSString *typeAttr = [[attrString componentsSeparatedByString:@","] firstObject];
NSString *typeName = [typeAttr substringWithRange:NSMakeRange(3, typeAttr.length - 4)];
// the default initialization
Class typeClass = NSClassFromString(typeName);
[self setValue:[[typeClass alloc] init] forKeyPath:keyPath];
}
return [self valueForKeyPath:keyPath];
}
// the generated setter method
void dynamicSetterMethodIMP(id self, SEL _cmd, id value) {
// get the property name out of selector name
// e.g. setLazyArray: -> lazyArray
NSString *propertyName = NSStringFromSelector(_cmd);
propertyName = [propertyName stringByReplacingOccurrencesOfString:@"set" withString:@""];
propertyName = [propertyName stringByReplacingOccurrencesOfString:@":" withString:@""];
propertyName = [NSString stringWithFormat:@"%@%@", [propertyName substringToIndex:1].lowercaseString, [propertyName substringFromIndex:1]];
NSString *keyPath = [NSString stringWithFormat:@"myVars.%@", propertyName];
[self setValue:value forKeyPath:keyPath];
}
// dynamic method resolution
+ (BOOL)resolveInstanceMethod:(SEL)aSEL {
if ([NSStringFromSelector(aSEL) containsString:@"set"]) {
class_addMethod([self class], aSEL, (IMP)dynamicSetterMethodIMP, "^?");
} else {
class_addMethod([self class], aSEL, (IMP)dynamicGetterMethodIMP, "[email protected]:");
}
return YES;
}
@end
Documentation
使用宏我猜。 –