关于 iOS 中数据交付

在 iOS 的数据交付(数据传递)方式中,常用的方式有:参数传递、Delegate、Notification、Block、KVO 和 Target-Action。下面逐一说明下这几种方式:

参数传递

这是最常用的一种方法了,就是在一个类中声明一个 public 的属性,提供给调用者,举个例子:

/* A.h */
@interface A : UIView;

@property (nonatomic, strong) UIButton *title;

@end
/* B.m */
A *a = [A alloc] init];
a.title = @"title";

这个就是最简单的参数传递的例子了,也是最常用的一种方式。

Delegate

在 iOS 中说到 delegate 自然就是想到 protocol,想想当初为了面试,还真不少背概念,其实也很好理解,举个比较形象的例子:

某神壕,想在深圳出售一套200方的房子(想想我干一辈子也买不起~~~),但神壕不想自己搞,然后交给了中介(delegate)去卖,但是神壕还是有一定要求的,比如最少多少钱、最好能达到多少钱等等(protocol),而买家则必须达到这种要求(实现 protocol方法),神壕才会卖,否则他就不干。

看完神壕卖房的例子,我想应该能大概理解 delegate 和 protocol 的关系了。

举例个实际应用:

/* 头文件 */
/* 定义一个协议 */
@protocol YHPhotoPickerViewControllerDelegate <NSObject>

- (void)YHPhotoPickerViewController:(YHSelectPhotoViewController *)PhotoPickerViewController selectedPhotos:(NSArray *)photos;
- (void)selectedPhotoBeyondLimit:(int)count currentView:(UIView *)view;

@end

@interface YHSelectPhotoViewController : UIViewController

@property(weak, nonatomic) id<YHPhotoPickerViewControllerDelegate> pickerDelegate;

@end

实现方法:

/* 实现类中的方法 */
- (void)finshToSelectPhoto {
    
    if ([self.pickerDelegate respondsToSelector:@selector(YHPhotoPickerViewController:selectedPhotos:)]){
       // todo some thing
    }
}

在这里将数据交付出去。先判断delegate是否存在,然后再判断是否实现的协议的相关内容(若不实现需要crash时可以在判断里加上断言),当delegate 和 protocol 都实现了,就可以进行数据的交付了。

调用方法:

@interface ViewController : UIViewController <YHPhotoPickerViewControllerDelegate>

#pragma mark - YHPhotoPickerViewController Delegate
- (void)YHPhotoPickerViewController:(YHSelectPhotoViewController *)PhotoPickerViewController selectedPhotos:(NSArray *)photos {
    // handle data
}

@end

这里处理交付的数据,需要实现协议方法

Notification

Notification,这东西又爱又恨,一不小心就坑到不要不要的,这里先不分析为什么,先说实现。Notification(观察者模式的一种实现) 和 Delegage 都是设计模块的一种,但是两种设计模式的使用场景不太一样。

先看下观察者模式(图片来自大话设计模式):

图片.png

这里就不详细说设计模式,我看了下大话设计模式这本书,还是说得比较形象,有兴趣的可以看下,但我还是比较喜欢黑书那本。

在 iOS 中,apple 已经封装好了 Notification,不需要我们实现,这里我们直接使用就可以了:

发送通知:

// object 就是交付的参数了,如果想传递多个参数时,可以使用集合来传递
[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationName" object:nil];

再看上面,新手很容易被坑到,object 并不是交付的参数,看另一个接口:

图片.png

userInfo 才是要交付的参数,object 是用来做过滤通知的,_ 有没有坑过呢,问下自己吧。

再看添加监听通知的方法:

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSNotificationName)aName object:(id)anObject;

这里也有objct,别纠结,直接看苹果 api 文档就好了:

图片.png

接收通知:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sensorStateChange:) name:UIDeviceProximityStateDidChangeNotification object:nil];

- (void)sensorStateChange:(NSNotificationCenter *)notification { ... }

其实苹果的api文档已经写得很详细了,如果有对接口方法有疑问,还是多去看下官方的接口文档。

Block

Block 可以理解为 OC 的匿名函数,也可以理解为 OC 中的一种特殊变量,它可以在两个对象之间将任意的代码块当做参数进行传递。

举个例子:

typedef void (^DictionaryResponseBlock)(NSDictionary *retDict);
typedef void (^errorBlock)(NSError *error);

+ (void)reqeustWeatherInfo:(NSString *)cityName
                      successCallback:(DictionaryResponseBlock)successCallback
                         failCallback:(errorBlock)failCallback;
                         
[XXXXX reqeustWeatherInfo:@"cityName" successCallback:^(NSDictionary *retDict) {
                // 代码块(你要处理的操作)
            } failCallback:^(NSError *error) {
                
            }];

关键还是 在两个对象之间将任意的代码块当做参数进行传递 这句话的理解,上面的代码实行就是把

^(NSDictionary *retDict) {
                // 代码块(你要处理的操作)
            }

这些代码块当作参数传递到别一个对象中使用。在使用block的时候,初学的时候遇到过很懵逼的问题,就是什么时候使用weak,是否需要strong回来,看到唐巧大神的公众号有几篇文章解释得非常好,就是self 持有 block,block 又持有 self 时,就会引起循环引用,这个时候就需要使用:

__weak __typeof(self)weakSelf = self;

这种情况,为防止block调用self时,self被释放的情况,就要使用:

__strong __typeof(weakSelf)strongSelf = weakSelf;

if (strongSelf) {

}

详细可以去看巧神的公众号。

KVO

KVO(Key - Value - Observer) 又是观察者模式的一种实现,简单点说就是键值监听者,指定的对象的属性被修改后,监听的对象就会收到通知。

举例:

// 1.注册观察者
[user addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:user.name];

// 2.回调方法
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {

}

// 3.移除观察者
[user removeObserver:self forKeyPath:@"name"];

}

在这里可以通过context的值进行数据交付。

Target-Action

Target-Action(目标-动作模式),看起来有点抽象化,简单点来说就是:当某事件发生时,我们会xxx(目标,也可以说对象)的xxx方法(动作或行动)。

最简的例子就是button的点击事件,这个就不单独举例了。

选择何种交付方式

其实对于选择何种交付方式,对我个人来说,这方面经验还是不足够,这里只介绍自己遇到的坑,有更好的建议的朋友望指点。

合理使用Notification

上面介绍过Notification时也说了,一不小心就坑得不要不要的,比如说你忘记把某个监听给移除了,这个就是很苦逼的事情,内心是很酸爽的。这个主要是编码不规范导致的。另一人主要原因还是Notification的影响面不可控制,没有办法确认处理地方法只有唯一,或者明确处理的地方,特别多人协助时就更加混乱。这里虽然说了Notification的使用很多不好的地方,但并不是强调Notification的不好,只有最合适的设计模式,没有好或者最坏的设计模式,所有能用的设计模式,都是前人的经验和总结,它们的存在都是经过了前人的检验的。比如网络状态的切换就很合适使用Notification。

少用block

其实能用block实现的东西都可以通过delegate来实现,但要区分怎么选择的话,那就是看回调的内容,如果回调要做的东西都是一致的就选择delegate;如果每次回调回来时要做的东西都不同,就选择block。

block除了上面介绍的时候说过会可能导致循环引用,我们可以weak引用来解决这个方法,但block还是有可能延长了对象的生命周期,而delegate就不会有这种问题,因为它本身就是弱的引用。这里为什么说尽量少用block,主要还是因为深受其害啊,目前公司的项目,不管是在网络层还是业务层,清一色的block,刚才接手原来的项目时,每次调试到一半,我去,block,又一个block,又一个block,这个时候我们根本不知道block里做了什么只能一个个跳进去查看,发现里面又有block,内心是各种草泥马的,一个方法里面有几个block,block里面还有block,这代码可读性真的感觉为0,一个方法有1,2百行的代码,混合着各个不同的任务,方法的单一性呢。。。

别一个问题,使用block的时候,回调的的代码和调用逻辑又放在一起了,很容易就出现那种一个方法几百行代码的情况,说好的方法单一性感觉又没有了。

总结

合理使用Notification,少用block。这里就只介绍这些了,其它的在后面的学习有所体会时再来补充了,如果有更好见解的朋友,望指出,大家多分享交流。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容