簡體   English   中英

Swift 3.2中的UIControl addTarget(_:action:for :)方法

[英]UIControl addTarget(_:action:for:) Method in Swift 3.2

我有一個類,通過以下addTarget調用將其稱為ClassA。

awesomeBtn.addTarget(nil, action: #selector(awesomeMethod), for: .touchUpInside)

當方法awesomeMethod在ClassA中時(即與addTarget調用相同的類),編譯器接受上述行。

但是,如果awesomeMethod不在ClassA中,則說它在ClassB中,那么編譯器會抱怨,並且我被迫在操作中指定類名。

awesomeBtn.addTarget(nil, action: #selector(ClassB.awesomeMethod), for: .touchUpInside)

在以前的Swift版本(不確定確切的版本)中,無論哪個類包含該方法,我都可以簡單地編寫以下內容。

awesomeBtn.addTarget(nil, action:("awesomeMethod"), forControlEvents:.touchUpInside)

想知道為什么會這樣,或者我做錯了什么,謝謝。

是的,如果您將方法名稱輸入錯誤的字符串更改為#selector ,則強制將方法從編譯時的String更改為只是一個運行時錯誤。 他們只是想盡早發現您的錯誤。

但是,如果awesomeMethod不在ClassA中,則說它在ClassB中,那么編譯器會抱怨,並且我被迫在操作中指定類名。

不,您可以指定一個實現該方法的@objc protocol

@objc protocol AwesomeProtocol {
    func awesomeMethod()
}

然后,即使您的類沒有實現該方法,也可以指定:

awesomeBtn.addTarget(nil, action: #selector(AwesomeProtocol.awesomeMethod), for: .touchUpInside)

注意:任何人似乎都沒有必要采用該協議。 該按鈕搜索響應者鏈,並使用找到的第一個匹配方法。 雖然,您應該為實現awesomeMethod的任何類采用該協議,以便Swift可以在編譯時檢測方法簽名中的錯誤。

基本上,Swift對您很好:)

在較早的版本中,您使用字符串文字或Selector(...)語法編寫選擇器。 這樣做的缺點是沒有編譯時檢查選擇器是否存在。 如果您在某處有錯字,則只能在運行時才能找到。 您不需要封閉類的名稱,因為選擇器只是方法的名稱,不包括封閉類。 在運行時,按鈕自己的邏輯將在您傳遞的target對象中找到該選擇器。 沒有人提供關於選擇器位於哪個類的信息。選擇器要么存在於target對象中,要么不存在。

現在,Swift進行了改進,並提供了一種用於編寫選擇器的#selector語法。 確實檢查選擇器是否有效。 編譯器需要查找具有相同名稱的方法的聲明。 這就是為什么您必須添加類名,以便編譯器知道要查找的原因。 否則,它將僅在當前類中查找它。 但是,這並不意味着選擇器在運行時將始終存在,因為在運行時,按鈕會檢查target是否具有該選擇器,因此,如果您傳入另一個類(而不是target的類)的選擇器,則按鈕仍然找不到選擇器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM