關于 iOS 中數(shù)據(jù)交付

在 iOS 的數(shù)據(jù)交付(數(shù)據(jù)傳遞)方式中畔濒,常用的方式有:參數(shù)傳遞、Delegate、Notification宠哄、Block毛嫉、KVO 和 Target-Action。下面逐一說明下這幾種方式:

參數(shù)傳遞

這是最常用的一種方法了暴区,就是在一個類中聲明一個 public 的屬性,提供給調(diào)用者房交,舉個例子:

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

@property (nonatomic, strong) UIButton *title;

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

這個就是最簡單的參數(shù)傳遞的例子了候味,也是最常用的一種方式隔心。

Delegate

在 iOS 中說到 delegate 自然就是想到 protocol硬霍,想想當初為了面試,還真不少背概念粱玲,其實也很好理解耐床,舉個比較形象的例子:

某神壕撩轰,想在深圳出售一套200方的房子(想想我干一輩子也買不起~~~),但神壕不想自己搞偎箫,然后交給了中介(delegate)去賣淹办,但是神壕還是有一定要求的恶复,比如最少多少錢谤牡、最好能達到多少錢等等(protocol),而買家則必須達到這種要求(實現(xiàn) protocol方法)恐疲,神壕才會賣,否則他就不干碳蛋。

看完神壕賣房的例子肃弟,我想應該能大概理解 delegate 和 protocol 的關系了茸炒。

舉例個實際應用:

/* 頭文件 */
/* 定義一個協(xié)議 */
@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

實現(xiàn)方法:

/* 實現(xiàn)類中的方法 */
- (void)finshToSelectPhoto {
    
    if ([self.pickerDelegate respondsToSelector:@selector(YHPhotoPickerViewController:selectedPhotos:)]){
       // todo some thing
    }
}

在這里將數(shù)據(jù)交付出去壁公。先判斷delegate是否存在,然后再判斷是否實現(xiàn)的協(xié)議的相關內(nèi)容(若不實現(xiàn)需要crash時可以在判斷里加上斷言)比肄,當delegate 和 protocol 都實現(xiàn)了芳绩,就可以進行數(shù)據(jù)的交付了撞反。

調(diào)用方法:

@interface ViewController : UIViewController <YHPhotoPickerViewControllerDelegate>

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

@end

這里處理交付的數(shù)據(jù)遏片,需要實現(xiàn)協(xié)議方法

Notification

Notification吮便,這東西又愛又恨,一不小心就坑到不要不要的许师,這里先不分析為什么僚匆,先說實現(xiàn)。Notification(觀察者模式的一種實現(xiàn)) 和 Delegage 都是設計模塊的一種咧擂,但是兩種設計模式的使用場景不太一樣逞盆。

先看下觀察者模式(圖片來自大話設計模式):

圖片.png

這里就不詳細說設計模式,我看了下大話設計模式這本書屋确,還是說得比較形象,有興趣的可以看下,但我還是比較喜歡黑書那本攻臀。

在 iOS 中焕数,apple 已經(jīng)封裝好了 Notification,不需要我們實現(xiàn)刨啸,這里我們直接使用就可以了:

發(fā)送通知:

// object 就是交付的參數(shù)了堡赔,如果想傳遞多個參數(shù)時设联,可以使用集合來傳遞
[[NSNotificationCenter defaultCenter] postNotificationName:@"NotificationName" object:nil];

再看上面善已,新手很容易被坑到,object 并不是交付的參數(shù)离例,看另一個接口:

圖片.png

userInfo 才是要交付的參數(shù)换团,object 是用來做過濾通知的,_ 有沒有坑過呢宫蛆,問下自己吧艘包。

再看添加監(jiān)聽通知的方法:

- (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文檔已經(jīng)寫得很詳細了想虎,如果有對接口方法有疑問,還是多去看下官方的接口文檔叛拷。

Block

Block 可以理解為 OC 的匿名函數(shù)舌厨,也可以理解為 OC 中的一種特殊變量,它可以在兩個對象之間將任意的代碼塊當做參數(shù)進行傳遞忿薇。

舉個例子:

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) {
                
            }];

關鍵還是 在兩個對象之間將任意的代碼塊當做參數(shù)進行傳遞 這句話的理解裙椭,上面的代碼實行就是把

^(NSDictionary *retDict) {
                // 代碼塊(你要處理的操作)
            }

這些代碼塊當作參數(shù)傳遞到別一個對象中使用。在使用block的時候煌恢,初學的時候遇到過很懵逼的問題骇陈,就是什么時候使用weak,是否需要strong回來瑰抵,看到唐巧大神的公眾號有幾篇文章解釋得非常好你雌,就是self 持有 block,block 又持有 self 時二汛,就會引起循環(huán)引用婿崭,這個時候就需要使用:

__weak __typeof(self)weakSelf = self;

這種情況,為防止block調(diào)用self時肴颊,self被釋放的情況氓栈,就要使用:

__strong __typeof(weakSelf)strongSelf = weakSelf;

if (strongSelf) {

}

詳細可以去看巧神的公眾號。

KVO

KVO(Key - Value - Observer) 又是觀察者模式的一種實現(xiàn)婿着,簡單點說就是鍵值監(jiān)聽者授瘦,指定的對象的屬性被修改后醋界,監(jiān)聽的對象就會收到通知。

舉例:

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

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

}

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

}

在這里可以通過context的值進行數(shù)據(jù)交付提完。

Target-Action

Target-Action(目標-動作模式)形纺,看起來有點抽象化,簡單點來說就是:當某事件發(fā)生時徒欣,我們會xxx(目標逐样,也可以說對象)的xxx方法(動作或行動)。

最簡的例子就是button的點擊事件打肝,這個就不單獨舉例了脂新。

選擇何種交付方式

其實對于選擇何種交付方式,對我個人來說粗梭,這方面經(jīng)驗還是不足夠争便,這里只介紹自己遇到的坑,有更好的建議的朋友望指點楼吃。

合理使用Notification

上面介紹過Notification時也說了始花,一不小心就坑得不要不要的,比如說你忘記把某個監(jiān)聽給移除了孩锡,這個就是很苦逼的事情酷宵,內(nèi)心是很酸爽的。這個主要是編碼不規(guī)范導致的躬窜。另一人主要原因還是Notification的影響面不可控制浇垦,沒有辦法確認處理地方法只有唯一,或者明確處理的地方荣挨,特別多人協(xié)助時就更加混亂男韧。這里雖然說了Notification的使用很多不好的地方,但并不是強調(diào)Notification的不好默垄,只有最合適的設計模式此虑,沒有好或者最壞的設計模式,所有能用的設計模式口锭,都是前人的經(jīng)驗和總結朦前,它們的存在都是經(jīng)過了前人的檢驗的。比如網(wǎng)絡狀態(tài)的切換就很合適使用Notification鹃操。

少用block

其實能用block實現(xiàn)的東西都可以通過delegate來實現(xiàn)韭寸,但要區(qū)分怎么選擇的話,那就是看回調(diào)的內(nèi)容荆隘,如果回調(diào)要做的東西都是一致的就選擇delegate恩伺;如果每次回調(diào)回來時要做的東西都不同,就選擇block椰拒。

block除了上面介紹的時候說過會可能導致循環(huán)引用晶渠,我們可以weak引用來解決這個方法凰荚,但block還是有可能延長了對象的生命周期,而delegate就不會有這種問題褒脯,因為它本身就是弱的引用浇揩。這里為什么說盡量少用block,主要還是因為深受其害啊憨颠,目前公司的項目,不管是在網(wǎng)絡層還是業(yè)務層积锅,清一色的block爽彤,剛才接手原來的項目時,每次調(diào)試到一半缚陷,我去适篙,block,又一個block箫爷,又一個block嚷节,這個時候我們根本不知道block里做了什么只能一個個跳進去查看,發(fā)現(xiàn)里面又有block虎锚,內(nèi)心是各種草泥馬的硫痰,一個方法里面有幾個block,block里面還有block窜护,這代碼可讀性真的感覺為0效斑,一個方法有1,2百行的代碼柱徙,混合著各個不同的任務缓屠,方法的單一性呢。护侮。敌完。

別一個問題,使用block的時候羊初,回調(diào)的的代碼和調(diào)用邏輯又放在一起了滨溉,很容易就出現(xiàn)那種一個方法幾百行代碼的情況,說好的方法單一性感覺又沒有了凳忙。

總結

合理使用Notification业踏,少用block。這里就只介紹這些了涧卵,其它的在后面的學習有所體會時再來補充了勤家,如果有更好見解的朋友,望指出柳恐,大家多分享交流伐脖。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末热幔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子讼庇,更是在濱河造成了極大的恐慌绎巨,老刑警劉巖瞻想,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逢捺,死亡現(xiàn)場離奇詭異,居然都是意外死亡编兄,警方通過查閱死者的電腦和手機歼跟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門和媳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人哈街,你說我怎么就攤上這事留瞳。” “怎么了骚秦?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵她倘,是天一觀的道長。 經(jīng)常有香客問我作箍,道長硬梁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任胞得,我火速辦了婚禮靶溜,結果婚禮上,老公的妹妹穿的比我還像新娘懒震。我一直安慰自己罩息,他們只是感情好,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布个扰。 她就那樣靜靜地躺著瓷炮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪递宅。 梳的紋絲不亂的頭發(fā)上娘香,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音办龄,去河邊找鬼烘绽。 笑死,一個胖子當著我的面吹牛俐填,可吹牛的內(nèi)容都是我干的安接。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼英融,長吁一口氣:“原來是場噩夢啊……” “哼盏檐!你這毒婦竟也來了歇式?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤胡野,失蹤者是張志新(化名)和其女友劉穎材失,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體硫豆,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡龙巨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了熊响。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恭应。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖耘眨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情境肾,我是刑警寧澤剔难,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站奥喻,受9級特大地震影響偶宫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜环鲤,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一纯趋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧冷离,春花似錦吵冒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞭空,卻和暖如春揪阿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背咆畏。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工南捂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人旧找。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓溺健,卻偏偏與公主長得像,于是被迫代替她去往敵國和親钮蛛。 傳聞我的和親對象是個殘疾皇子矿瘦,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容