2016-08-19 55 views
2

我想將函數的選擇器傳遞給另一個函數。現在我只是傳遞字符串,並做幾個if語句。如果我可以將實際的函數選擇器傳遞給函數,我可以消除所有if語句。傳遞選擇器(函數名稱)在swift中運行

我目前的功能:

func getBtn(i: String, f: String) -> UIBarButtonItem 
{ 
    let btn: UIButton = UIButton(); 
    btn.frame=CGRectMake(0,0,30,30) 
    btn.setBackgroundImage(UIImage(named:i), forState: UIControlState.Normal) 
    if f == "funcOne"{ btn.addTarget(self, action: #selector(self.funcOne), forControlEvents:.TouchUpInside) } 
    else if f == "funcTwo"{ btn.addTarget(self, action: #selector(self.funcTwo), forControlEvents:.TouchUpInside) } 
    else if f == "funcThree"{ btn.addTarget(self, action: #selector(self.funcThree), forControlEvents:.TouchUpInside) } 
    else if f == "funcFour"{ btn.addTarget(self, action: #selector(self.funcFour), forControlEvents:.TouchUpInside) } 
    // etc. 
    let barBtn = UIBarButtonItem(customView: btn) 
    return barBtn; 
} 

用法:

items.append(self.getBtn("checkmark",f:"funcOne")); 

我想怎麼能夠做到:

func getBtn(i: String, f: SOME_TYPE_OF_THING) -> UIBarButtonItem 
{ 
    let btn: UIButton = UIButton(); 
    btn.frame=CGRectMake(0,0,30,30) 
    btn.setBackgroundImage(UIImage(named:i), forState: UIControlState.Normal) 
    btn.addTarget(self, action: #selector(f), forControlEvents:.TouchUpInside) 
    let barBtn = UIBarButtonItem(customView: btn) 
    return barBtn; 
} 

用法:

items.append(self.getBtn("checkmark",f:self.funcOne)); 

回答

3

#selector()語法的用途是爲了避免在必須將選擇器編寫爲字符串時出現錯誤的可能錯誤。儘管如此,您可以自由地編寫Selector(f)而不是使用#selector()語法。

但是,它甚至會更好,如果f被自身類型爲選擇:

func getBtn(i: String, f: Selector) -> UIBarButtonItem 

這樣的話,你可以繼續使用#selector但這樣做在呼叫:

items.append(self.getBtn("checkmark",f:#selector(funcOne))) 

getBtn您將直接通過f作爲按鈕操作。

+0

感謝您的釘牢。我沒有收到任何錯誤。正是我所希望的。將在構建中進行測試。 –

+0

完美無瑕。謝謝。將在2分鐘內接受。 –

+0

很高興幫助。把它看作僅僅是將'#selector'的使用「推回」到行動的早期階段的一種方式。而不是在被調用者中執行它,我們在調用者中執行它。 – matt

0

你也可以將函數作爲參數傳遞給swift參數本質上就是方法簽名。這裏有一個簡單的例子,將在操場上運行:

func myFunc(s:String) -> String 
{ 
    return ("Hello \(s)") 
} 

func myOtherFunc(s:String) -> String 
{ 
    return ("Goodbye \(s)") 
} 

func someOtherFunc(aFunction:String -> String) -> String 
{ 
    return aFunction("test") 
} 

print(someOtherFunc(myFunc)) 
print(someOtherFunc(myOtherFunc)) 

我不知道這是你想要的,但它有時幫助。你可以這樣做:

items.append(self.getBtn("checkmark",f:funcOne)) 

然後更改self.getBtn方法以期望函數。像這樣的:

func funcOne() 
{ 
    print("Executing func one") 
} 

func getBtn(i: String, f:() ->()) -> UIBarButtonItem 
{ 
    let btn: UIButton = UIButton(); 
    btn.frame=CGRectMake(0,0,30,30) 
    btn.setBackgroundImage(UIImage(named:i), forState: UIControlState.Normal) 
    btn.addTarget(self, action: f, forControlEvents:.TouchUpInside) 
    let barBtn = UIBarButtonItem(customView: btn) 
    return barBtn; 
} 
+0

你可以在Swift中傳遞一個函數作爲參數,但是你不能在需要Objective-C選擇器的地方傳遞一個函數(即作爲'action:'參數),所以這是行不通的。 – matt

+1

很不幸顯示未經測試的代碼,特別是當它不能編譯時。 – matt