比方说,我有一个MyUITextViewSubclass,它继承自UITextView和从UITextField继承的MyUITextFieldSubclass,这两个子类都包含很多相同的方法和属性,以便为这些UI控件添加类似的行为.
由于UITextView和UITextField从不同的类继承,是否有一个简单的方法来创建一个抽象类来组合所有重复的代码?换句话说,是否可以创建一个可以从这两个子类继承的抽象类,然后只覆盖两者之间不同的方法?
我到目前为止所知道的
>我知道Objective-C不支持多重继承(从两个或更多个类继承)
>我知道我可以使用Categories添加常用的方法,但是我不认为这会解决覆盖init方法或添加私有属性
解决方法
建立在Amin的答案上,这是怎么做的呢?
步骤1:创建一个TextSurrogateHosting协议,该协议将包含您需要从要添加到这两个子类的方法访问的UITextField和UITextView子类的所有方法.这可能是一个文本和setText:方法,以便您的方法可以访问和设置文本字段或文本视图的文本.它可能看起来像这样:
SPWKTextSurrogateHosting.h
#import <Foundation/Foundation.h> @protocol SPWKTextSurrogateHosting <NSObject> - (NSString *)text; - (void)setText:(NSString *)text; @end
步骤2:创建一个TextSurrogate类,其中包含您希望在UITextField和UITextView子类之间共享的所有方法.将这些方法添加到协议中,以便我们可以在Xcode中使用代码完成,并避免编译器警告/错误.
SPWKTextSurrogate.h
#import <Foundation/Foundation.h> #import "SPWKTextSurrogateHosting.h" @protocol SPWKTextSurrogating <NSObject> @optional - (void)appendQuestionMark; - (void)appendWord:(NSString *)aWord; - (NSInteger)characterCount; - (void)capitalize; @end @interface SPWKTextSurrogate : NSObject <SPWKTextSurrogating> /* We need to init with a "host",either a UITextField or UITextView subclass */ - (id)initWithHost:(id<SPWKTextSurrogateHosting>)aHost; @end
SPWKTextSurrogate.m
#import "SPWKTextSurrogate.h" @implementation SPWKTextSurrogate { id<SPWKTextSurrogateHosting> _host; } - (id)initWithHost:(id<SPWKTextSurrogateHosting>)aHost { self = [super init]; if (self) { _host = aHost; } return self; } - (void)appendQuestionMark { _host.text = [_host.text stringByAppendingString:@"?"]; } - (void)appendWord:(NSString *)aWord { _host.text = [NSString stringWithFormat:@"%@ %@",_host.text,aWord]; } - (NSInteger)characterCount { return [_host.text length]; } - (void)capitalize { _host.text = [_host.text capitalizedString]; } @end
步骤3:创建您的UITextField子类.它将包含三种必要的样板方法,将无法识别的方法调用转发到您的SPWKTextSurrogate.
SPWKTextField.h
#import <UIKit/UIKit.h> #import "SPWKTextSurrogateHosting.h" #import "SPWKTextSurrogate.h" @interface SPWKTextField : UITextField <SPWKTextSurrogateHosting,SPWKTextSurrogating> @end
SPWKTextField.m
#import "SPWKTextField.h" @implementation SPWKTextField { SPWKTextSurrogate *_surrogate; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { _surrogate = [[SPWKTextSurrogate alloc] initWithHost:self]; } return self; } #pragma mark Invocation Forwarding - (void)forwardInvocation:(NSInvocation *)anInvocation { if ([_surrogate respondsToSelector:[anInvocation selector]]) { [anInvocation invokeWithTarget:_surrogate]; } else { [super forwardInvocation:anInvocation]; } } - (NSMethodSignature*)methodSignatureForSelector:(SEL)selector { NSMethodSignature* signature = [super methodSignatureForSelector:selector]; if (!signature) { signature = [_surrogate methodSignatureForSelector:selector]; } return signature; } - (BOOL)respondsToSelector:(SEL)aSelector { if ([super respondsToSelector:aSelector] || [_surrogate respondsToSelector:aSelector]) { return YES; } return NO; } @end
步骤4:创建您的UITextView子类.
SPWKTextView.h
#import <UIKit/UIKit.h> #import "SPWKTextSurrogateHosting.h" #import "SPWKTextSurrogate.h" @interface SPWKTextView : UITextView <SPWKTextSurrogateHosting,SPWKTextSurrogating> @end
SPWKTextView.m
#import "SPWKTextView.h" #import "SPWKTextSurrogate.h" @implementation SPWKTextView { SPWKTextSurrogate *_surrogate; } - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { _surrogate = [[SPWKTextSurrogate alloc] initWithHost:self]; } return self; } #pragma mark Invocation Forwarding - (void)forwardInvocation:(NSInvocation *)anInvocation { if ([_surrogate respondsToSelector:[anInvocation selector]]) { [anInvocation invokeWithTarget:_surrogate]; } else { [super forwardInvocation:anInvocation]; } } - (NSMethodSignature*)methodSignatureForSelector:(SEL)selector { NSMethodSignature* signature = [super methodSignatureForSelector:selector]; if (!signature) { signature = [_surrogate methodSignatureForSelector:selector]; } return signature; } - (BOOL)respondsToSelector:(SEL)aSelector { if ([super respondsToSelector:aSelector] || [_surrogate respondsToSelector:aSelector]) { return YES; } return NO; } @end
步骤5:使用它:
SPWKTextField *textField = [[SPWKTextField alloc] initWithFrame:CGRectZero]; SPWKTextView *textView = [[SPWKTextView alloc] initWithFrame:CGRectZero]; textField.text = @"The green fields"; textView.text = @"What a wonderful view"; [textField capitalize]; [textField appendWord:@"are"]; [textField appendWord:@"green"]; [textField appendQuestionMark]; NSLog(@"textField.text: %@",textField.text); // Output: The Green Fields are green? [textView capitalize]; [textView appendWord:@"this"]; [textView appendWord:@"is"]; NSLog(@"textView.text: %@",textView.text); // Output: What A Wonderful View this is
这种模式可以解决你的问题.希望 :)