我想创建一个可以从两个自定义类继承的类。
你有什么想法吗?
请看下面我的例子:
头等舱:
@interface UIZoomableView : UIView
{
UITapGestureRecognizer *_tapGestureRecognizer;
}
和实施:
- (void)onDoubleTap:(UITapGestureRecognizer *)sender
{
CGSize newSize;
CGPoint centerPoint = self.center;
if ([self isSmall])
{
newSize = [self bigSize];
}
else
{
newSize = [self smallSize];
}
[UIView animateWithDuration:0.3 animations:^{
self.size = newSize;
self.center = centerPoint;
}];
}
第二课:
@interface UIDraggableView : UIView
UIPanGestureRecognizer *_panGestureRecognizer;
@end
执行:
- (void)handlePan:(UIPanGestureRecognizer*)sender
{
..
}
我想创建一个可缩放和可拖动的自定义视图。
你有什么想法吗? (没有复制代码..)
我认为类似协议,但我想要基类的默认值?
我如何使用协议或类似协议来实现这一点。
谢谢你的回复!
Objective-C不支持多重继承。您可以使用协议,组合和消息转发来实现相同的结果。
协议定义了一组对象必须实现的方法(也可以使用可选方法)。组合基本上是包含对另一个对象的引用并在需要其功能时调用该对象的技术。消息转发是一种允许对象将消息传递到其他对象的机制,例如,通过合成包含的对象。
Apple参考:
因此,在您的情况下,Composition可能是一个解决方案,下面是示例代码
@interface ClassA : NSObject {
}
-(void)methodA;
@end
@interface ClassB : NSObject {
}
-(void)methodB;
@end
@interface MyClass : NSObject {
ClassA *a;
ClassB *b;
}
-(id)initWithA:(ClassA *)anA b:(ClassB *)aB;
-(void)methodA;
-(void)methodB;
@end
@implementation MyClass
-(id)initWithA:(ClassA *)anA b:(ClassB *)aB {
a = anA ;
b = aB ;
}
-(void)methodA {
[a methodA] ;
}
-(void)methodB {
[b methodB] ;
}
@end
如果您不想在MyClass中实现ClassA和ClassB中的所有方法,则可以在MyClass中使用Message Forwarding来处理所有方法调用。只要ClassA和ClassB没有任何常用方法,下面的工作正常。
@implementation MyClass
-(id)initWithA:(ClassA *)anA b:(ClassB *)aB {
a = anA ;
b = aB ;
}
//This method will be called, when MyClass can not handle the method itself
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([a respondsToSelector:[anInvocation selector]])
[a invokeWithTarget:someOtherObject];
else if ([b respondsToSelector:[anInvocation selector]])
[b invokeWithTarget:someOtherObject];
else
[super forwardInvocation:anInvocation];
}
@end
Objective C中最接近多重继承的是类别。这些是为已存在的类添加其他方法的机制。
请注意,这有一些重要的限制:
- 您无法使用类别添加属性或ivars,但您可以使用 相关对象 得到类似的效果;
- 编译器不会告诉您是否具有在类和类别中声明的具有相同名称的方法,或者在两个类别中,因此您必须小心避免名称冲突;
- 这不会显示为正确的类(因为Objective C没有多重继承),因此您的代码中不会出现任何内容
ScrollableZoomableView
继承自 ScrollableView
和 ZoomableView
。这在Objective C中是不可能的(例如与C ++不同)。
- 你需要的
-ObjC
将文件与类别链接时标记,否则你会得到 unrecognized selector
运行代码时出错;
- 您无法在此期间调用您的代码
-init
要么 +initialize
,因为那些属于基类。您需要明确初始化您的属性。你仍然可以使用 +load
虽然;
- 您也不能拦截dealloc,因此您可能需要小心显式注销您的侦听器。
你想要这样的东西:
@interface UIView (Zoomable)
@property (nonatomic) UITapGestureRecognizer * my_tapGestureRecognizer;
@end
@implementation UIView (Zoomable)
-(void)my_enableZooming() {
self.my_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(my_onDoubleTap:)];
self.my_tapGestureRecognizer.numberOfTapsRequired = 2;
[self addGestureRecognizer:self.my_tapGestureRecognizer];
}
-(void)my_disableZooming() {
[self removeGestureRecognizer:self.my_tapGestureRecognizer];
self.my_tapGestureRecognizer = nil;
}
-(void)my_onDoubleTap:(UITapGestureRecognizer *)sender {
...
}
-(UITapGestureRecognizer)my_tapGestureRecognizer {
return objc_getAssociatedObject(self, @selector(my_tapGestureRecognizer));
}
-(void)setMy_tapGestureRecognizer:(UITapGestureRecognizer)value {
objc_setAssociatedObject(self, @selector(my_tapGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
@interface UIView (Draggable)
@property (nonatomic) UIPanGestureRecognizer * my_panGestureRecognizer;
@end
@implementation UIView (Draggable)
-(void)my_enableDragging() {
self.my_panGestureRecognizer = ...;
}
-(void)my_disableDragging() {
...
}
-(void)my_handlePan:(UIPanGestureRecognizer*)sender {
...
}
-(UIPanGestureRecognizer)my_panGestureRecognizer {
return objc_getAssociatedObject(self, @selector(my_panGestureRecognizer));
}
-(void)setMy_panGestureRecognizer:(UIPanGestureRecognizer)value {
objc_setAssociatedObject(self, @selector(my_panGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
您可能还会在objc.io中查看有关行为的这篇文章。您可以创建可拖动和可缩放的行为,然后将它们添加到您想要的任何视图中。
这是文章。