美文网首页
四、协议

四、协议

作者: faterman | 来源:发表于2018-01-25 13:37 被阅读9次

    OC中不支持多继承和抽象类,因而出现了协议。其实就是把一个某一系列相同功能类应该实现的方法定义在协议中,编写类的时候遵守这个协议,那么也意味着该类应该实现对应的方法。
    在iOS编程实践中,协议的比较总要的两个应用场景是:

    • 实现代理设计模式
    • 实现protocol形式的项目组件化

    基本语法

    协议也可以继承协议

    @protocol <#protocol name#> <NSObject>
    
    <#methods#>
    
    @end
    

    代理模式

    定义一套接口,某对象若想接受另一个对象的委托,则需遵从此接口,以便成为它的代理。之后委托者可以向代理请求数据,或者发出事件回调。

    比较经典的使用是UITableView。对于一个视图而言,它的内部应该仅包含一定数据源格式时视图如何展示的逻辑。而不应该包括数据和交互逻辑。所以将数据的获取组装作为一个数据源代理(data source),把与视图的交互反馈作为代理(delegate)。最终实现数据与业务逻辑的解耦。

    另外一个场景是网络获取数据,Effect Objective-C中有这样一个例子:


    image.png

    代理的属性修饰

    代理的属性修饰符应该使用weak,复合语义,因为委托方并不持有代理,两者生命周期无关。并且也避免了引用,因为代理一般会持有委托方。

    @optional和@required

    @optional用来定义可选协议方法,默认是可选的。@required用来定义必须实现的协议方法。
    可以使用respondsToSelector来判断代理是否能够响应协议方法。

    使用位段(bitfield)来缓存响应能力

    位段的实现:

    struct {
            unsigned int didReceiceData     :1;
            unsigned int didFailWithError   :1;
        } _delegateFlags;
    

    这里每一个值可以存储0或1,在设置代理时通过respondsToSelector赋值,以后使用的时候判断缓存值即可。

    一个例子

    --------------- interface 文件 ---------------
    #import <Foundation/Foundation.h>
    
    @class FTMNetworkFetcher;
    
    @protocol FTMNetworkFetcherDelegate <NSObject>
    @optional
    - (void)networkFetcher:(FTMNetworkFetcher *)fetcher
            didReceiveData:(NSData *)data;
    - (void)networkFetcher:(FTMNetworkFetcher *)fetcher
            didFailWithError:(NSError *)error;
    @end
    
    @interface FTMNetworkFetcher : NSObject
    @property (weak, nonatomic) id<FTMNetworkFetcherDelegate> delegate;
    @end
    
    --------------- implementation 文件 ---------------
    #import "FTMNetworkFetcher.h"
    
    @interface FTMNetworkFetcher () {
        struct {
            unsigned int didReceiceData     :1;
            unsigned int didFailWithError   :1;
        } _delegateFlags;
    }
    @end
    
    @implementation FTMNetworkFetcher
    
    - (void)setDelegate:(id<FTMNetworkFetcherDelegate>)delegate {
        _delegate = delegate;
        _delegateFlags.didReceiceData = [_delegate respondsToSelector:@selector(networkFetcher:didReceiveData:)];
        _delegateFlags.didFailWithError = [_delegate respondsToSelector:@selector(networkFetcher:didFailWithError:)];
    }
    
    @end
    

    相关文章

      网友评论

          本文标题:四、协议

          本文链接:https://www.haomeiwen.com/subject/voxvaxtx.html