![](/img/trans.png)
[英]Swift: UIScrollView & UIControl - addTarget | addGestureRecognizer - Not working as expected
[英]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.