17.iOS中继承了拥有delegate属性控件的问题

来源:互联网 发布:简短软件开发合同 编辑:程序博客网 时间:2024/06/10 07:20

        在iOS中,我们很多情况下都需要自定义控件,而自定义控件我们通常都是先继承自系统控件,然后进行一系列扩充,但我发现当我继承了本身拥有delegate属性的控件时,想要在自定义控件类内部拿到delegate方法出现了问题,下面我以UIScrollView为例进行说明:

1、第一个想法是直接在重写父类的初始化方法时设置self.delegate = self,这样虽然可以在类内部直接调用代理方法,但是这样严重的问题是如果外部(比如在viewController中)为该控件设置了代理,那么内部设置的代理就被覆盖了,所以在发生相应事件时也不会调用类内部的代理方法了。

- (instancetype)initWithFrame:(CGRect)frame{    self = [super initWithFrame:frame];    self.delegate = self;    return self;}- (instancetype)initWithCoder:(NSCoder *)aDecoder{    self = [super initWithCoder:aDecoder];    self.delegate = self;    return self;}

2、第二个想法是为这个新类重新设置一个区别于delegate的myDelegate属性,然后重新定制所有父类所遵循的代理协议的所有方法,然后也是在类内部设置delegate = self,然后在所有delegate方法内部向新的delegate发送对应的消息,这样在类内部和外部都可以获取到delegate方法了,但是这样同样也有一个问题就是外部只能规定设置myDelegate属性,万一在外部不小心设置了delegate属性,所有的方法都失去了效果。所以也不是很理想。

3、在查阅了相关资料后,找到了一个折中的方法,名为delegate挂钩,即:

                Objective-C是一门oop的语言,oop的特性有哪些呢:多态. 
               可以用这特性去解决这一问题: 
              * 重载子类的delegate属性为myDelegate(这个名字可以自定义)
              * 在子类里重写delegate方法,在ViewController里调用的delegate其实是子类自己的myDelegate. 
              * 然后让父类的delegate指向自己.在子类里实现的delegate方法里调用子类的delegate的方法.

       这样说来可能有一些绕,我通过代码进行说明:
@implementation CenteredScrollView@synthesize delegate = _myDelegate;//重载父类delegate属性#pragma mark - 初始化相关- (instancetype)initWithFrame:(CGRect)frame{    self = [super initWithFrame:frame];    [super setDelegate:self];    //关键点设置父类delegate为self    return self;}- (instancetype)initWithCoder:(NSCoder *)aDecoder{    self = [super initWithCoder:aDecoder];    [super setDelegate:self];    return self;}#pragma mark - UIScrollViewDelegate- (void)scrollViewDidScroll:(UIScrollView *)scrollView{    if ([self.delegate respondsToSelector:@selector(scrollViewDidScroll:)]){        //这里调用的delegate即为myDelegate,在外部设置的delegate也是myDelegate。        [self.delegate scrollViewDidScroll:scrollView];    }}- (void)scrollViewDidZoom:(UIScrollView *)scrollView{     if ([self.delegate respondsToSelector:@selector(scrollViewDidZoom:)]){         [self.delegate scrollViewDidZoom:scrollView];     }}<pre name="code" class="objc"><pre name="code" class="objc">...
@end 

         通过以上的相关设置,即可以在类内部和外部都获取到delegate方法了。
         但是这种方法虽然 相比前两种要好,但仍然会有问题,比如在tableView中设置dataSource时这种方法就没有效果,这可能和苹果内部的源码有关系了。建议以后如果出现这种情况,除了必须要继承自该类型控件外,可以直接继承自UIView,然后再在UIView中封装其他控件,再全部订制delegate方法,这种做法虽然麻烦,但是一般不会出现问题。
         如果大家对于这种情况有什么好的方法,可以与我交流。the end~






0 0
原创粉丝点击