I am creating a method for a class in swift with 2 arguments, and they are both optional. however, I need at least one of them to be populated for the method to successfully work, it doesn't matter which one
func someMethod(arg1: Sometype?, arg2: Sometype?)-> Void {
//I need at least one argument to
//be populated to do what i need
}
In Objective-c we could throw an Assert if both of these object was nil. in Swift i"m wondering if there is a better way to do this than an assert.
I agree with Airspeed Velocity that you should use overloads here, but I'd make them differently. Get rid of the optionals entirely.
func someMethod(#arg1: Sometype)-> Void {}
func someMethod(#arg2: Sometype)-> Void {}
func someMethod(#arg1: Sometype, #arg2: Sometype) -> Void {}
At which point, it should be obvious that these are really different methods:
func someMethodWithArg1(arg1: Sometype)-> Void {}
func someMethodWithArg2(arg2: Sometype)-> Void {}
func someMethod(#arg1: Sometype, #arg2: Sometype) -> Void {}
To make this concrete, consider if we were making a FixedLengthString
class that you could pass a length to, or an existing string, or you could pass both and it'd repeat the string until it filled the length.
What you're describing would be:
func makeString(length: Int?, string: String?) -> FixedString
But rather than that, just make the methods:
func makeStringWithLength(length: Int) -> FixedString
func makeStringFromString(string: String) -> FixedString
func makeStringByFillingWith(string: String, totalLength: Int) -> FixedString
This makes it clearer how everything works, and you can't call it incorrectly. This is how you should be doing it in ObjC, too.
You could use overloading instead:
// arg1 cannot be nil
func someMethod(arg1: Int, arg2: Int?)-> Void {
println("arg2 was nil")
somePrivateMethod(arg1,arg2)
}
// arg2 cannot be nil
func someMethod(arg1: Int?, arg2: Int)-> Void {
println("arg1 was nil")
somePrivateMethod(arg1,arg2)
}
// this version is needed to avoid annoying "ambiguous call"
// errors when passing two non-optionals in...
func someMethod(arg1: Int, arg2: Int)-> Void {
println("neither was nil")
somePrivateMethod(arg1,arg2)
}
private func somePrivateMethod(arg1: Int?, arg2: Int?)-> Void {
// private method in which at least arg1 or arg2 will be guaranteed non-nil
}
someMethod(1, nil) // prints "arg2 was nil"
someMethod(nil, 1) // prints "arg1 was nil"
someMethod(1, 1) // prints "neither was nil"
// but if you try this:
someMethod(nil, nil) // error: cannot find an overload for 'someMethod'
// that accepts an argument list of type '(nil, nil)'
The downside of this is that the caller is forced to unwrap the arguments – they just can't pass two optionals in without checking at lest one of them is non-nil. But this is a feature, not a bug! As it means it is physically impossible for the caller to accidentally call the API "the wrong way" and generate an assertion.
Of course, this does lead to the question of whether really you want multiple overloads that take different numbers of arguments or different types (see Rob's answer), which is also worth considering in the context of your use case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With