I am looking for a proper way to handle a invalid argument during a initialization.
I am unsure how to do it using Swift as the init has't a return type. How can I tell whoever is trying to initialize this class that you are doing something wrong?
init (timeInterval: Int) {
if timeInterval > 0
self.timeInterval = timeInterval
else
//???? (return false?)
}
Thank you!
Use a failable initializer. Such an initializer looks very similar to a regular designated initializer, but has a '?' character right after init
and is allowed to return nil
. A failable initializer creates an optional value.
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty { return nil }
self.species = species
}
}
See Apple's documentation on failable initializers for more detail.
In swift, you can't really abort a task half way through execution. There are no exceptions in swift and in general the philosophy is that aborting a task is dangerous and leads to bugs, so it just should't be done.
So, you verify a value like this:
assert(timeInterval > 0)
Which will terminate the program if an invalid value is provided.
You should also change timeInterval
to be a UInt
so that there will be a compiler error if anybody tries to give a < 0
value or an integer value that could be < 0.
It's probably not the answer you're looking for. But the goal is to check for bad parameters as early as possible, and that means doing it before you create any objects with those parameters. Ideally the check should be done at compile time but that doesn't always work.
I think this is the best solution, took it from:How should I handle parameter validation Swift
class NumberLessThanTen {
var mySmallNumber: Int?
class func instanceOrNil(number: Int) -> NumberLessThanTen? {
if number < 10 {
return NumberLessThanTen(number: number)
} else {
return nil
}
}
@required init() {
}
init(number: Int) {
self.mySmallNumber = number
}
}
let iv = NumberLessThanTen.instanceOrNil(17) // nil
let v = NumberLessThanTen.instanceOrNil(5) // valid instance
let n = v!.mySmallNumber // Some 5
In the Swift book by Apple, at the very bottom of this section:https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/swift_programming_language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-XID_399
They say:
When to Use Assertions
Use an assertion whenever a condition has the potential to be false,
but must definitely be true in order for your code to continue
execution. Suitable scenarios for an assertion check include:
An integer subscript index is passed to a custom subscript
implementation, but the subscript index value could be too low or too
high. A value is passed to a function, but an invalid value means that
the function cannot fulfill its task. An optional value is currently
nil, but a non-nil value is essential for subsequent code to execute
successfully.
This sounds exactly like your situation!
Thus your code should look like:
init (timeInterval: Int) {
assert (timeInterval > 0, "Time Interval Must be a positive integer")
// Continue your execution normally
}