经过一番研究后,我“放弃”了使用标准 Apple 对象。暂时不存在。我已经创建了自己的代理,它非常简单(现在仅适用于“外观:”)。
让我们解释一下。我想在 NSObject 子类上设置“textColor”的外观,我们称之为“FLObject”。使 FLObject 符合 UIAppearance 协议并覆盖外观方法。在这种方法中,您应该返回一个代理类(我创建的那个):
+ (id)appearance
{
return [FLAppearance appearanceForClass:[self class]];
}
这个怎么运作?FLAppearance 为外观ForClass: 方法传递的每个类创建一个自身实例。如果您为同一个类调用两次,则返回相同的实例。
然后,您可以执行以下操作:
[[FLObject appearance] setTextColor:[UIColor redColor]];
FLAppearance 覆盖 forwardInvocation: 方法,因此它接受所有发送的方法。然后,它将所有调用放入一个数组中。当 FLObject 被初始化时,一个简单的调用
[(FLAppearance *)[FLAppearance appearanceForClass:[self class]] startForwarding:self];
将开始发送调用并设置外观。当然,这需要一些调整和错误检查,但我认为这是一个好的开始。
@interface FLAppearance ()
@property (strong, nonatomic) Class mainClass;
@property (strong, nonatomic) NSMutableArray *invocations;
@end
static NSMutableDictionary *dictionaryOfClasses = nil;
@implementation FLAppearance
// this method return the same object instance for each different class
+ (id) appearanceForClass:(Class)thisClass
{
// create the dictionary if not exists
// use a dispatch to avoid problems in case of concurrent calls
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (!dictionaryOfClasses)
dictionaryOfClasses = [[NSMutableDictionary alloc]init];
});
if (![dictionaryOfClasses objectForKey:NSStringFromClass(thisClass)])
{
id thisAppearance = [[self alloc]initWithClass:thisClass];
[dictionaryOfClasses setObject:thisAppearance forKey:NSStringFromClass(thisClass)];
return thisAppearance;
}
else
return [dictionaryOfClasses objectForKey:NSStringFromClass(thisClass)];
}
- (id)initWithClass:(Class)thisClass
{
self = [self initPrivate];
if (self) {
self.mainClass = thisClass;
self.invocations = [NSMutableArray array];
}
return self;
}
- (id)init
{
[NSException exceptionWithName:@"InvalidOperation" reason:@"Cannot invoke init. Use appearanceForClass: method" userInfo:nil];
return nil;
}
- (id)initPrivate
{
if (self = [super init]) {
}
return self;
}
-(void)forwardInvocation:(NSInvocation *)anInvocation;
{
// tell the invocation to retain arguments
[anInvocation retainArguments];
// add the invocation to the array
[self.invocations addObject:anInvocation];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [self.mainClass instanceMethodSignatureForSelector:aSelector];
}
-(void)startForwarding:(id)sender
{
for (NSInvocation *invocation in self.invocations) {
[invocation setTarget:sender];
[invocation invoke];
}
}