2017-03-20 26 views
0

我想創建一個通用按鈕創建函數到我傳遞表示結果點擊按鈕的結果作用的封閉使用。我的代碼如下。但是,我收到以下錯誤: #selector的參數無法引用屬性。任何解決方法的建議?我不想編寫單獨的函數,除了目標操作外,其他所有內容都是相同的。斯威夫特作爲參數傳遞關閉由選擇器功能

func myButton(textColor tColor:UIColor , title:String, 
       _ buttonFcn: (UIButton) -> Void, 
       titleSize:CGFloat=30) -> UIButton { 
    let newButton = UIButton(type: .System) 
    let bgColor = UIColor(red:204/255, green:204/255, blue:204/255, alpha:1.0) 
    newButton.backgroundColor = bgColor 

    newButton.setTitle(title, forState: .Normal) 
    newButton.setTitleColor(tColor, forState: .Normal) 

    newButton.titleLabel?.font = newButton.titleLabel?.font.fontWithSize(titleSize) 


    newButton.addTarget(self, action:#selector(buttonFcn), 
         forControlEvents: 
          UIControlEvents.TouchUpInside) 

    return newButton 
} 
+0

的可能的複製[我可以#selector指的是斯威夫特封閉?](http://stackoverflow.com/questions/36983633/can-i-make-selector-refer-to-a-closure-in -swift) – davecom

回答

2

的問題是,所述目標動作機構是一個Objective-C機構,因此在概念前提是,動作選擇器是一個對象方法。你所需要的,因此,有一些基於NSObject的-對象具有該功能的方法,然後它可以作爲目標。

因此,如果每種情況下的目標和動作有所不同,您需要傳遞的是對目標的引用以及選擇器字符串。 Swift會在這方面發出警告,但是如果你知道如何正確地形成一個選擇器字符串,你當然可以避開它;你只是不能使用#selector語法,所以如果你錯誤地構造了選擇器字符串,你將面臨崩潰的風險。但是這正是我們以前在Objective-C時代所做的所有事情,所以如果這是您的目標,請繼續前進。

完全人造的,但工作示例:

func buttonMaker(target:NSObject, selectorString:String) -> UIButton { 
    let b = UIButton(type:.system) 
    b.setTitle("Testing", for: .normal) 
    b.addTarget(target, action: Selector(selectorString), for: .touchUpInside) 
    b.sizeToFit() 
    return b 
} 

這裏是如何從一個視圖控制器撥打:

func doButton(_ sender:Any) { 
    print("ha!") 
} 

override func viewDidLoad() { 
    super.viewDidLoad() 
    // Do any additional setup after loading the view, typically from a nib. 
    let b = buttonMaker(target:self, selectorString:"doButton:") 
    b.frame.origin = CGPoint(x:100, y:100) 
    self.view.addSubview(b) 
} 

當我們輕點按鈕,我們不崩潰(更確切地說,我們打印「哈」),因爲我知道如何正確地選擇字符串。但是,正如你所看到的,爲了實現這個目標,我必須完全放棄使用#selector,所以安全就在窗外。如果我寫的不正確的選擇我的字符串 - 例如,如果我拼寫錯了,或省略冒號 - 我們就已經墜毀,機上按鈕水龍頭,就像我們用所有的時間斯威夫特#selector和Objective-C @selector前被髮明。

+0

感謝您的解釋。最後我用您的解決方案,即通過在selectorString,但使用#selector語法的變化(以保持編譯時檢查)和case語句派遣的selectorString。 '''FUNC buttonMaker(selectorString:字符串,..) - >的UIButton { 開關selectorString { 案 「func1的」: newButton.addTarget(個體,動作:#selector(func1的), forControlEvents:UIControlEvents.TouchUpInside ) case func2: } return newButton }''' – femibyte