I have a UIDatePicker
. After a date is selected I call this method
func goToNextScreen(selectedDate: Date) {
//...
}
Now I have added a UIButton
. In that button action I want to call the same method goToNextScreen
without any date value. Date value is optional in next screen. I tried the following code
btn.addTarget(self, action: #selector(goToNextScreen), for: .touchUpInside)//goToNextScreen(_:)
@objc func goToNextScreen(selectedDate: Date? = nil) {
//...
}
When the button is tapped the app crashes.
How to solve this without adding another method? If it is not possible why my approach doesn't work
What is happening here is, the button's internal logic is trying to pass the sender, which is a UIButton
into your method's Date
parameter. However, the sender parameter won't get passed if your method don't have any arguments.
Optional parameters don't really work in this situation. What you can do however, is to create another parameterless overload for goToNextScreen
:
@objc func goToNextScreen() {
goToNextScreen(selectedDate: nil)
}
And change
btn.addTarget(self, action: #selector(goToNextScreen), for: .touchUpInside)
to
btn.addTarget(self, action: #selector(goToNextScreen as () -> Void), for: .touchUpInside)
so that it different between the two overloads.
Note that the reason why just writing #selector(goToNextScreen)
is ambiguous is because you have two methods named goToNextScreen
, and Swift needs to resolve to one of them. But it can't with just the name. Here is a similar situation:
class Foo {
@objc func f() {}
func f(x: Int) {}
let selector: Selector = #selector(f) // ambiguous use of f
}
Edit: You can't really do this without creating another method. Selectors are inflexible things.
It's not possible in this case re-use the same method. You should create a new one without parameters or whose parameters are UIButton
(or a more generic type, often is Any
) and the UIEvent
. Here's the explanation of the Target-Action mechanism: UIControl .
I thought you've to try this
var selectedDate = Date()
btn.addTarget(self, action: #selector(goToNextScreen), for: .touchUpInside)//goToNextScreen(_:)
@objc func goToNextScreen(_ sender: UIButton)
{
selectedDate ?? self.datePickerDate : Date()
}
Using Any
as sender
type and casting to Date
works
//add button Target
btn.addTarget(self, action: #selector(goToNextScreen(_:)), for: .touchUpInside)
//Call with date value
goToNextScreen(Date())
@objc func goToNextScreen(_ selectedDate: Any) {
nextVC.date = selectedDate as? Date
//...
}
sender
paramter of UIButton
is casted to Date
which is reason of crash , it should be a UIButton
btn.addTarget(self, action: #selector(btnClicked), for: .touchUpInside)//goToNextScreen(_:)
@objc func btnClicked(_ sender:UIButton) {
// call next here
goToNextScreen()
}
func goToNextScreen(_ selectedDate: Date? = nil) {
if let date = selectedDate { }
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.