聽名字可能有點不認識魄咕,但是介紹下其作用,就會覺得恍然大悟员凝,原來它就叫反射。
0x01 什么是反射
這種動態(tài)編程機制驾霜,可以讓Objective-C
語言更加靈活,說到反射买置,首先我們需要弄清楚什么是反射:
在運行中程序檢查自己和軟件運行環(huán)境的能力粪糙,它可以根據(jù)它發(fā)現(xiàn)的進行改變。
通俗的講就是 反射可以在運行時根據(jù)類名獲得類的信息忿项。
0x01 為什么要用反射
當你要做一個軟件可以安裝插件的功能蓉冈,你連插件的類型名稱都不知道,怎么示例化這個對象呢轩触?
因為程序是支持插件的(第三方)寞酿,在開發(fā)的時候并不清楚。
所以脱柱,無法在代碼中new
出來伐弹,但反射可以,通過反射榨为,動態(tài)加載程序集惨好,然后讀出類,檢查標記之后再實例化對象随闺,就可以獲得正確的類示例日川。
反射的目的就是為了擴展未知的應用。
iOS中反射及其用處
由于Objective-C
是動態(tài)語言矩乐,其具備在運行時操作類的方案龄句。
我們可以很方便的通過類名創(chuàng)建指定的類,并且可以通過系統(tǒng)提供的API
獲取類中的方法绰精,屬性等信息撒璧。
通過反射機制,我們可以實現(xiàn)很多有意思的功能笨使,比如:
json->model方案
后臺消息確定動態(tài)跳轉頁面
將相似功能的代碼抽象組合成更加通用的框架卿樱,比如全局跳轉,消息中心
0x02 反射怎么用
- 根據(jù)字符串/操作獲取信息
NSClassFromString // Obtains a class by name.
NSStringFromClass // Returns the name of a class as a string.
NSSelectorFromString // Returns the selector with a given name.
NSStringFromSelector // Returns a string representation of a given selector.
NSStringFromProtocol // Returns the name of a protocol as a string.
NSProtocolFromString // Returns a the protocol with a given name.
- 簡單操作
// 根據(jù)字符串名獲取Class對象
Class clazz = NSClassFromString(@"Car") ;
//直接使用Class來創(chuàng)建對象
id car = [[clazz alloc] init] ;
// 使用performSelector:動態(tài)執(zhí)行方法
[car performSelector:NSSelectorFromString(startEngine)];
- 與運行時一起用功能更加強大
// 獲取成員變量列表
Ivar _Nonnull * class_copyIvarList(Class cls, unsigned int *outCount);
// 獲取屬性列表
objc_property_t _Nonnull * class_copyPropertyList(Class cls, unsigned int *outCount);
// 獲取方法列表
Method _Nonnull * class_copyMethodList(Class cls, unsigned int *outCount);
// 還有許多強大的API可以提供操作
0x03 優(yōu)缺點
優(yōu)點:
1. 增加程序靈活性硫椰,避免將程序寫死代碼中
2. 代碼簡潔繁调,提高代碼復用率,外部調用方便
3. 對于任意一個類靶草,都能夠知道這個類的所有屬性和方法蹄胰;對于任意一個對象都可以調用它任意的方法
缺點:
1. 使用反射,抽象度比較高奕翔,不利于代碼閱讀
2. 對字符串要求比較嚴格裕寨,需要完整對應上,如果代碼采用了混淆方案,則難以維護
3. 私有方法可以被訪問宾袜,破壞封裝性