iOS runtime實戰應用:關聯對象

在開始之前建議先閱讀iOS runtime的基礎理解篇:iOS內功篇:runtime

有筒子在面試的時候,遇到這樣一個問題:“如何給NSArray添加一個屬性(不能使用繼承)”,筒子立馬蒙逼了,不能用繼承,難道用分類?但是分類貌似只能添加方法不能添加屬性啊,筒子百思不得其解,直到后來接觸到了runtime才恍然大悟。

什么是關聯對象

關聯對象是指某個OC對象通過一個唯一的key連接到一個類的實例上。
舉個例子:xiaoming是Person類的一個實例,他的dog(一個OC對象)通過一根繩子(key)被他牽著散步,這可以說xiaoming和dog是關聯起來的,當然xiaoming可以牽著多個dog。

怎樣關聯對象

runtime提供給我們的方法:

//關聯對象
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
//獲取關聯的對象
id objc_getAssociatedObject(id object, const void *key)
//移除關聯的對象
void objc_removeAssociatedObjects(id object)

變量說明:

id object:被關聯的對象(如xiaoming)
const void *key:關聯的key,要求唯一
id value:關聯的對象(如dog)
objc_AssociationPolicy policy:內存管理的策略

objc_AssociationPolicy policy的enum值有:

OBJC_ASSOCIATION_ASSIGN = 0,          
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, 
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,  
OBJC_ASSOCIATION_RETAIN = 01401,       
OBJC_ASSOCIATION_COPY = 01403

當對象被釋放時,會根據這個策略來決定是否釋放關聯的對象,當策略是RETAIN/COPY時,會釋放(release)關聯的對象,當是ASSIGN,將不會釋放。
值得注意的是,我們不需要主動調用removeAssociated來接觸關聯的對象,如果需要解除指定的對象,可以使用setAssociatedObject置nil來實現。

關聯對象的應用

1、添加公共屬性

這是最常用的一個模式,通常我們會在類聲明里面添加屬性,但是出于某些需求(如前言描述的情況),我們需要在分類里添加一個或多個屬性的話,編譯器就會報錯,這個問題的解決方案就是使用runtime的關聯對象。
應用舉例:
我們需要自定義一個tabbar,并暴露公共的屬性和方法。(讀者們可以思考下使用繼承和分類實現的優點和不足之處)

@interface UITabBarController (Custom)@property (nonatomic, strong) SUCustomTabbar * customTabbar;@end
#import "UITabBarController+Custom.h"
#import <objc/runtime.h>@implementation UITabBarController (Custom)- (void)setCustomTabbar:(UIView *)customTabbar {//這里使用方法的指針地址作為唯一的keyobjc_setAssociatedObject(self, @selector(customTabbar), customTabbar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}- (UIView *)customTabbar {return objc_getAssociatedObject(self, @selector(customTabbar));
}//其他方法...@end

這樣,我們就可以像原生的tabbar一樣使用自定義的tabbar:

[self.tabBarController.customTabbar doSomgthig];

2、添加私有成員變量

有時候,需要在分類中添加不想暴露在公共聲明的成員變量。
應用舉例:給按鈕添加點擊時間的回調

@interface UIButton (Callback)- (instancetype)initWithFrame:(CGRect)frame callback:(void (^)(UIButton *))callbackBlock;@end
@interface UIButton ()@property (nonatomic, copy) void (^callbackBlock)(UIButton * button);@end@implementation UIButton (Callback)- (void (^)(UIButton *))callbackBlock {return objc_getAssociatedObject(self, @selector(callbackBlock));
}- (void)setCallbackBlock:(void (^)(UIButton *))callbackBlock {objc_setAssociatedObject(self, @selector(callbackBlock), callbackBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
}- (instancetype)initWithFrame:(CGRect)frame callback:(void (^)(UIButton *))callbackBlock {if (self = [super initWithFrame:frame]) {self.callbackBlock = callbackBlock;[self addTarget:self action:@selector(didClickAction:) forControlEvents:UIControlEventTouchUpInside];}return self;
}- (void)didClickAction:(UIButton *)button {self.callbackBlock(button);
}@end

讀者思考:以上代碼是否會存在內存管理的問題

3、關聯KVO觀察者
有時候我們在分類中使用KVO,推薦使用關聯的對象作為觀察者,盡量避免對象觀察自身。
此應用模式不再舉例,有興趣的讀者可以自行深入研究,或者將代碼貼到評論處。

思考

1、關聯對象更多的應用模式?
2、關聯對象是否是解決問題的首選?
3、關聯對象的副作用?

歡迎大家交流探討。

?

轉自:http://www.jianshu.com/p/c68cc81ef763

轉載于:https://www.cnblogs.com/dannygao/p/7374852.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282682.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282682.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282682.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

黑龍江科技大學計算機考研復試科目,2020年黑龍江科技大學計算機應用技術考研經驗分享...

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓育明考研備考策略隨著IT業的迅猛發展&#xff0c;各高校計算機專業報名火爆&#xff0c;甚至文科學生跨專業報考時都會選擇計算機。計算機專業競爭日趨激烈&#xff0c;那么如何在充分發揮公共科目優勢的同時&#xff0c;盡量縮小專…

Mysql數據庫安全性問題【防注入】

一、SQL注入實例 后臺的插入語句代碼&#xff1a; $unsafe_variable $_POST[user_input]; mysql_query("INSERT INTO table (column) VALUES ($unsafe_variable)"); 當POST的內容為&#xff1a; value); DROP TABLE table;--以上的整個SQL查詢語句變成&#xff1…

Unexpected end of JSON input while parsing near錯誤解決方式(網上的方法)

原本是想創建一個create-react-app來著&#xff0c;但是在創建的中間會出現Unexpected end of JSON input while parsing near... 的錯誤。 在網上找到了一些方法&#xff0c;首先是清空npm的緩存。 npm cache clean --force 氮素&#xff0c;然并卵。near后面的內容變化了一下…

解決Qt5 Creator無法切換輸入法(fcitx),Ubuntu中不能使用搜狗輸入法錄入漢字問題...

2016年6月8日修正&#xff0c;ubuntu 16.04 Qt5.7.0 以及 Qt5.6.1均測試通過在Qt5.3之前&#xff0c;我發布過解決辦法 解決Qt5 Creator無法切換輸入法&#xff08;fcitx&#xff09;&#xff0c;不能錄入漢字問題&#xff0c;Qt5.4以及Qt5.5&#xff0c;舊辦法失效&#xff0c…

目前市場上用于個人計算機的硬盤尺寸是,第5章-硬盤(計算機組裝與維護).docx

ADDIN CNKISM.UserStyle一、選擇題1.磁盤存儲器的主要技術指標有多項&#xff0c;下面不屬于硬盤指標的是( )。A.存儲容量B.單碟容量C.轉速D.帶寬2.硬盤的平均尋道時間通常以毫秒為單位測量&#xff0c;是指( )。A.磁頭從一個柱面移到另一個隨機距離遠的柱面所需的平均時間B.…

Xmemcached學習筆記一(安裝memcached)

memcached有三種java客戶端 第一種&#xff1a;Com.danga 包下面的memcached&#xff0c;需引入jar(本人用的是memcached-2.5.2.jar 文末附上附件需要的可以下載) 第二種&#xff1a;spyMemcached 第三種&#xff1a;XMemcached 據說第三種是使用最簡單&#xff0c;最好用的&a…

WrapPanel 實現虛擬化

WrapPanel 實現虛擬化控件名&#xff1a;VirtualizingWrapPanel作者&#xff1a;WPFDevelopersOrg原文鏈接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用大于等于.NET40&#xff1b;Visual Studio 2022;項目使用 MIT 開源許可協議&#xff1b;眾…

pdo連接mysql數據庫(簡潔明了)

一 實例化pdo對象 $dsn "mysql:dbnametest;host127.0.0.1"; $pdo new PDO($dsn,root,root);二 數據查詢 1、如果不根據用戶傳過來的值進行操作,可以直接query sql $dsn "mysql:dbnametest;host127.0.0.1"; $pdo new PDO($dsn,root,root); $sql &qu…

一次微信小程序的快速開發體驗

起因 事情是這樣的 一天早上組里還早激烈的討論某個項目的可用性和發展前景&#xff0c;突然老大說了句&#xff0c;能不能做個小程序的版本呢&#xff1f;然后大家紛紛討論起來&#xff0c;有反對有支持&#xff0c;我就說了一句&#xff0c;剛出來的時候搞過一會。。。然后就…

造數據時踏過的坑

1.在產生隨機數時,在數據規模很大的時候很難出現自己要的模型,比如某個條件的數據量,此時要寫一個方法,來造一批這樣的數據 2.將控制數量,文件路徑寫成配置文件的形式,以免重復打包 3.輸入輸出文件夾,可以配置以免重復打包 轉載于:https://www.cnblogs.com/rocky-AGE-24/p/7376…

如何證明 ConcurrentDictionary 字典操作不全是線程安全的

前言最近&#xff0c;看到一篇文章&#xff0c;講到《ConcurrentDictionary字典操作竟然不全是線程安全的&#xff1f;》。首先&#xff0c;這個結論是正確的&#xff0c;但文中給出的一個證明例子&#xff0c;我覺得是有問題的。相關代碼如下&#xff1a;using System.Collect…

微型計算機及接口技術試題,1月自考微型計算機及其接口技術試題及答案解析...

《1月自考微型計算機及其接口技術試題及答案解析》由會員分享&#xff0c;可在線閱讀&#xff0c;更多相關《1月自考微型計算機及其接口技術試題及答案解析(11頁珍藏版)》請在人人文庫網上搜索。1、精品自學考試資料推薦全國 2018年 1月自考微型計算機及其接口技術試題課程代碼…

16-djongo中間件學習

目錄 前戲 我們在前面的課程中已經學會了給視圖函數加裝飾器來判斷是用戶是否登錄&#xff0c;把沒有登錄的用戶請求跳轉到登錄頁面。我們通過給幾個特定視圖函數加裝飾器實現了這個需求。但是以后添加的視圖函數可能也需要加上裝飾器&#xff0c;這樣是不是稍微有點繁瑣。 學完…

PHP基礎(必須熟練掌握的基礎)

<?php/*** 三元運算符的應用*/ /* $a 10; $b 15; echo $a > $b ? 1 : 0; */ // 注:php7新添加的運算符比較運算符x<>y // 如果x和y相等,就返回0,如果x>y,就返回1,如果x的值小于y,就返回-1/* $a "aaa"; $b "bbb"; echo $a.$b; *//*** …

子進程無法從標準輸入讀取數據

每個process對象最多只能調用一次start()方法&#xff0c;join([timeout])方法會阻塞調用process對象的進程&#xff0c;直到timeout時間超時&#xff0c;或者process進程退出。如果timeout設置為None&#xff0c;則無超時時間。對于linux操作系統的進程管理&#xff0c;父進程…

Eclipse控制項目的訪問名稱

Eclipse控制web項目的訪問名稱 web項目的訪問路徑&#xff08;名稱&#xff09;修改 1.點擊項目右鍵-》properties找到Context root 修改成我們需要的名字即可轉載于:https://www.cnblogs.com/pypua/articles/7379950.html

計算機一級選擇題已做完確認,計算機一級選擇題(附答案)

點擊藍字關注我們(1)按照需求功能的不同&#xff0c;信息系統已形成各種層次&#xff0c;計算機應用于管理是開始于:()A)信息處理B)人事管理C)決策支持D)事務處理正確答案&#xff1a;A解析&#xff1a;計算機用于管理&#xff0c;起源于計算機在辦公應用中對大量信息、數據的處…

參加51CTO培訓,PMP考試通過啦

為什么選擇考PMP&#xff1f;先介紹下自己的情況&#xff0c;畢業三年&#xff0c;單位類似于平臺&#xff0c;不做技術&#xff0c;常態的工作是文案、商務、市場都會涉及些&#xff0c;對未來也有些迷茫。受前輩點撥可以學一些通用的技能&#xff0c;于是我選擇了PMP&#xf…

如何查看服務器并發請求連接數

https://wenku.baidu.com/view/fb553d795acfa1c7aa00cc27?pcf2#1 轉載于:https://www.cnblogs.com/linewman/p/9918760.html

C# 二十年語法變遷之 C# 5 和 C# 6參考

C# 二十年語法變遷之 C# 5 和 C# 6參考https://benbowen.blog/post/two_decades_of_csharp_ii/自從 C# 于 2000 年推出以來&#xff0c;該語言的規模已經大大增加&#xff0c;我不確定任何人是否有可能在任何時候都對每一種語言特性都有深入的了解。因此&#xff0c;我想寫一系…