2016-07-30 29 views
15

Swift和iOS開發中的超級newb在這裏。當添加UIButton目標時,「classname has no member functionname」

我正在關注在單個視圖iOS應用中實現自定義控件的this tutorial。這是一個Swift 2教程,但到目前爲止,我一直在努力將所有內容都轉換爲3(我使用XCode 8 Beta)。

我有一個自定義類,RatingControl,連接到故事板中的View

在類的構造函數中,我創建了一個按鈕:

let button = UIButton(frame: CGRect(x: 0, y: 0, width: 44, height: 44)) 
button.backgroundColor = UIColor.red() 

於是,我試圖給該按鈕的動作。該教程說我應該做它像這樣:

button.addTarget(self, action: #selector(RatingControl.ratingButtonTapped(_:)), 
for: .touchDown)  

,然後創建,在同RatingControl類,方法:

func ratingButtonTapped(button: UIButton) { 
    print("Button pressed ") 
} 

但是當我編譯,它抱怨:

類型「RatingControl」沒有任何成員「ratingButtonTapped」

我已經100%確定函數在那裏,在課堂上,並且正確命名。 Full source

有什麼明顯的我失蹤了嗎?

我的嘗試:

  • 新增@objc類定義爲每this answer(但似乎對於斯威夫特唯一怪異,不是嗎?)

  • 製造ratingButtonTapped()明確public (但看起來應該是不必要的)

  • 擺弄字符串而不是選擇器s,button.addTarget(self, action: "RatingControl.ratingButtonTapped", for: .touchDown)等等,但是之後就會崩潰。

+3

A-ha! XCode的自動提示功能回答了這個問題:我現在需要使用'RatingControl.ratingButtonTapped',沒有括號。這工作正常,現在編譯。我可以刪除這個問題 - 但如果有人想提供一個答案更詳細地解釋這個問題,以及*爲什麼會發生這種情況,我們可能能夠爲未來具有相同問題的讀者提供一個有用的資源? –

+2

我認爲這個問題很好,只要它標記爲'swift3',因爲一旦Swift 3成爲標準,這可能會導致一些混淆。關於選擇器的一個提示是:如果方法與調用者在同一個範圍內,你可以調用'self.methodName'而不是'ClassName.methodName',這只是一個美觀的細節。 – xoudini

+0

@xoudini謝謝! –

回答

11

發生這種情況是因爲斯威夫特3已經改變了它處理的第一個參數名的方式。在調用函數時必須使用所有參數名稱,除非明確聲明_被聲明爲參數名稱。

,如果你宣佈你的函數,你用什麼作爲你的選擇是罰款:

func ratingButtonTapped(_ button: AnyObject) { 
    print("Button pressed ") 
} 

你也可以用這個作爲你的選擇:

#selector(RatingControl.ratingButtonTapped(button:)) 

添加@objc到類定義根據這個答案(但似乎 怪異的斯威夫特唯一的事情,沒有?)

您的代碼可能在Swift中,但是您在編寫代碼爲Cocoa Touch(iOS框架)時正在與Objective-C運行時交互。 選擇器是一個需要Objective-C運行時可見的函數。你大部分時間都是免費的,因爲你在一個最終從NSObject(如UIViewController)繼承的類中實現了這個功能。如果你有一個不能從NSObject繼承的Swift類,那麼你可以添加@objc來使類和方法對Objective-C運行時可見。

15

在Swift 3中,方法參考爲:func ratingButtonTapped(button: UIButton)變爲ratingButtonTapped(button:)

所以,使用#selector(RatingControl.ratingButtonTapped(button:))也可以。

如果你想保持#selector(RatingControl.ratingButtonTapped(_:)),那麼你需要聲明ratingButtonTapped方法:

func ratingButtonTapped(_ button: UIButton) { //<- `_` 
    print("Button pressed ") 
} 

如果你在課堂上只有一個ratingButtonTapped方法,可以解決此選擇的#selector(RatingControl.ratingButtonTapped)或簡單地(從內部RatingControl類)#selector(ratingButtonTapped)

+0

只是很好的答案,謝謝 – manukv

+0

如果函數沒有任何參數,這會發生什麼? – kashish

+0

@ kashish,目前尚不清楚你的問題是什麼。更好地開始你自己的線索,你會得到或被引導到更合適的答案。 – OOPer

3

如果你想調用另一個類的視圖控制器中的動作,你可以試試這個。

使用ViewController()作爲您的目標。使用ViewController.functionName作爲選擇器。不要使用像「vc」這樣的視圖控制器變量的輔助方法,否則你將無法訪問ViewController中的對象。

下面是一個例子目標:

self.addTarget(ViewController(), action:#selector(ViewController.Test(_:)), for: UIControlEvents.touchDragInside) 

在您的視圖控制器,這裏有一個例子行動

@IBAction func Test(_ sender: Any?) { 
    print("Goodtime was here") 

}

在目標,你必須添加(),但不該動作的選擇器。你不必調用@IBAction,它可以只是func。有些人使用@objc或公開任何這些行動前綴應該工作。

查看,如果該操作位於不同的Class或ViewController中,則必須將該類引用放入目標和操作的選擇器中。否則,它將嘗試始終在同一個文件中調用該操作,而不管它在Selector中是否正確。同樣,如果操作在同一個文件中使用,則自我爲目標並在操作的選擇器內部。

乾杯

2

當SWIFT 3追加按鈕目標首先你需要在class

class SomeClass { 

    // ... 

    let button = UIButton() 
    // configure button to taste... 

    button.addTarget(self, 
        action: #selector(doSomething), 
        for: .touchUpInside) 

    // ... 

    @objc public func doSomething() { 
    print("hello, world!") 
    } 

    // ... 

} 
相關問題