iOS開發中@selector的理解與應用

來源:互聯網
上載者:User
iOS開發中@selector的理解與應用

@selector 是什麼:

 

1、一種類型 SEL
2、代表你要發送的訊息(方法), 跟字串有點像, 也可以互轉.: NSSelectorFromString() / NSSelectorFromString()

3、可以理解為類似函數指標的東西--是能讓Objective-C動態調用方法的玩意.--是 object-c 的動態後綁定技術 可以通過字串 訪問的函數指標
4、其實就是訊息響應函數---選一個訊息響應的函數地址給你的action
5、@selector(function_name) 即取得一個function的id objc_msgxxx 系列函數是全域的
performSelector 是NSObject成員方法,ms效果差不多

Objective-C的動態後綁定技術:可以通過字串訪問的函數指標
typedef obj_handler * SEL;
  關於objc_msgSend & performSelector系列函數的問題。 1。objc_msgSend:
書上說這個函數是OC編譯器在編譯的時候,遇到類似[object foo]的寫法時,就會把相應OC的文法轉成C的objc_msgSend函數了。還有相應的objc_msgSendSuper


2。關於performSelector系列:
performSelector, performSelector:withDelay:, performSelector:withObj:withDelay, XXX...
除了第一個,後面幾個都可以指定一個延遲時間,然後就把selector放到當前線程的runloop中等待調用。從方法名上看,感覺performSelector == performSelector:withDelay系列中,delay為0的情況。


我的問題是:
1、objc_msgSend這個函數是直接由[object foo]轉過來的嗎。 也就是說,中間不會轉成performSelector吧。objc_msgSend是同步的嗎。
2、performSelector:withDelay:這個是非同步了,放進runloop中,那如果performSelector和performSelector:withDelay(delay為0時)一樣的話, 那performSelector也是非同步嗎。也要進runloop嗎。 
答:
1、是的,不要performSelector了,直接objc_msgSend。事實上,這個是OC編譯時間就轉好的,也就是OC編譯的時候就把對象調用轉成函數的call了
2、是的,delay為0也進runloop,這樣做的好處是可以不阻住當前調用performSelector:withDelay:的方法的執行

怎樣證實上邊的答案沒有問題。
很簡單,寫幾個測試代碼,然後打斷點一跑,在運行時看調用棧。
觀察程式運行最好的方法總是調試器~


3、delegate屬性使用assign的原因。

循環參考

所有的引用計數系統,都存在迴圈應用的問題。例如下面的參考關聯性:

對象a建立並引用到了對象b.

對象b建立並引用到了對象c.

對象c建立並引用到了對象b.

這時候b和c的引用計數分別是2和1。當a不再使用b,調用release釋放對b的所有權,因為c還引用了b,所以b的引用計數為1,b不會被釋放。b不釋放,c的引用計數就是1,c也不會被釋放。從此,b和c永遠留在記憶體中。

這種情況,必須打斷循環參考,通過其他規則來維護參考關聯性。比如,我們常見的delegate往往是assign方式的屬性而不是retain方式的屬性,賦值不會增加引用計數,就是為了防止delegation兩端產生不必要的循環參考。如果一個UITableViewController 對象a通過retain擷取了UITableView對象b的所有權,這個UITableView對象b的delegate又是a,如果這個delegate是retain方式的,那基本上就沒有機會釋放這兩個對象了。自己在設計使用delegate模式時,也要注意這點。

因為循環參考而產生的記憶體泄露也是Instrument無法發現的,所以要特別小心。

4、delegate屬性使用assign的原因。

還有一些用法會讓系統擁有對象的所有權。比如NSObject 的performSelector:withObject:afterDelay 。如果有必要,需要顯示的調用cancelPreviousPerformRequestsWithTarget:selector:object: ,否則有可能產生記憶體泄露。

iPhone開發中,動態調用類和方法:

NSClassFromString

NSSelectorFromString

正常來說,

id myObj = [[NSClassFromString(@"MySpecialClass") alloc] init];

id myObj = [[MySpecialClass alloc] init];

是一樣的。但是,如果你的程式中並不存在MySpecialClass這個類,下面的寫法會出錯,而上面的寫法只是返回一個Null 物件而已。

因此,在某些情況下,可以使用NSClassFromString來進行你不確定的類的初始化。

比如在iPhone中,NSTask可能就會出現這種情況,所以在你需要使用NSTask時,最好使用:

[[NSClassFromString(@"NSTask") .....]]

而不要直接使用[NSTask ...]這種寫法。

NSClassFromString的好處是:

1 弱化串連,因此並不會把沒有的Framework也link到程式中。

2 不需要使用import,因為類是動態載入的,只要存在就可以載入。


@selector

@selector 是什麼。

1一種類型 SEL
2代表你要發送的訊息(方法), 跟字串有點像, 也可以互轉.: NSSelectorFromString() / NSSelectorFromString()

3可以理解為類似函數指標的東西--是能讓Objective-C動態調用方法的玩意.--是 object-c 的動態後綁定技術 可以通過字串 訪問的函數指標
4其實就是訊息響應函數---選一個訊息響應的函數地址給你的action
5@selector(function_name) 即取得一個function的id

objc_msgxxx 系列函數是全域的
performSelector 是NSObject成員方法,ms效果差不多

關於objc_msgSend & performSelector系列函數的問題。 1。objc_msgSend:
書上說這個函數是OC編譯器在編譯的時候,遇到類似[object foo]的寫法時,就會把相應OC的文法轉成C的objc_msgSend函數了。還有相應的objc_msgSendSuper


2。關於performSelector系列:
performSelector, performSelector:withDelay:, performSelector:withObj:withDelay, XXX...
除了第一個,後面幾個都可以指定一個延遲時間,然後就把selector放到當前線程的runloop中等待調用。從方法名上看,感覺performSelector == performSelector:withDelay系列中,delay為0的情況。


我的問題是:
1。objc_msgSend這個函數是直接由[object foo]轉過來的嗎。 也就是說,中間不會轉成performSelector吧。objc_msgSend是同步的嗎。
2。performSelector:withDelay:這個是非同步了,放進runloop中,那如果performSelector和performSelector:withDelay(delay為0時)一樣的話, 那performSelector也是非同步嗎。也要進runloop嗎。


剛開始看cocoa,有很多不懂的。
tianya 2011-05-11 08:13
答:
1、是的,不要performSelector了,直接objc_msgSend。事實上,這個是OC編譯時間就轉好的,也就是OC編譯的時候就把對象調用轉成函數的call了
2、是的,delay為0也進runloop,這樣做的好處是可以不阻住當前調用performSelector:withDelay:的方法的執行

怎樣證實上邊的答案沒有問題。
很簡單,寫幾個測試代碼,然後打斷點一跑,在運行時看調用棧。
觀察程式運行最好的方法總是調試器~

respondsToSelector

3、delegate屬性使用assign的原因。

循環參考

所有的引用計數系統,都存在迴圈應用的問題。例如下面的參考關聯性:

對象a建立並引用到了對象b.

對象b建立並引用到了對象c.

對象c建立並引用到了對象b.

這時候b和c的引用計數分別是2和1。當a不再使用b,調用release釋放對b的所有權,因為c還引用了b,所以b的引用計數為1,b不會被釋放。b不釋放,c的引用計數就是1,c也不會被釋放。從此,b和c永遠留在記憶體中。

這種情況,必須打斷循環參考,通過其他規則來維護參考關聯性。比如,我們常見的delegate往往是assign方式的屬性而不是retain方式的屬性,賦值不會增加引用計數,就是為了防止delegation兩端產生不必要的循環參考。如果一個UITableViewController 對象a通過retain擷取了UITableView對象b的所有權,這個UITableView對象b的delegate又是a,如果這個delegate是retain方式的,那基本上就沒有機會釋放這兩個對象了。自己在設計使用delegate模式時,也要注意這點。

因為循環參考而產生的記憶體泄露也是Instrument無法發現的,所以要特別小心。


4、delegate屬性使用assign的原因。

還有一些用法會讓系統擁有對象的所有權。比如NSObject 的performSelector:withObject:afterDelay 。如果有必要,需要顯示的調用cancelPreviousPerformRequestsWithTarget:selector:object: ,否則有可能產生記憶體泄露。

iPhone開發中,動態調用類和方法:

NSClassFromString

NSSelectorFromString

正常來說,

id myObj = [[NSClassFromString(@"MySpecialClass") alloc] init];

id myObj = [[MySpecialClass alloc] init];

是一樣的。但是,如果你的程式中並不存在MySpecialClass這個類,下面的寫法會出錯,而上面的寫法只是返回一個Null 物件而已。

因此,在某些情況下,可以使用NSClassFromString來進行你不確定的類的初始化。

比如在iPhone中,NSTask可能就會出現這種情況,所以在你需要使用NSTask時,最好使用:

[[NSClassFromString(@"NSTask") .....]]

而不要直接使用[NSTask ...]這種寫法。

NSClassFromString的好處是:

1 弱化串連,因此並不會把沒有的Framework也link到程式中。

2 不需要使用import,因為類是動態載入的,只要存在就可以載入。


for (int c=0; c<[classNames count]; c++) {

    NSString *className=[classNames objectAtIndex:c];

    id class=[[NSClassFromString(className) alloc] init];

    for (int i=0; i<[params count]; i++) {

        [class performSelector:NSSelectorFromString([NSString stringWithFormat:@"setA%i",i])];

    }

}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.