Swift:Non-Nil Optional Value Raising a Nil Exception

Swift : non-nil optional value raising a nil exception

it's an outlet to a textfield but it seems to not unwrap in the prepareForSegue function

That comment reveals your misconception. Things happen in a order, which I discuss here: https://stackoverflow.com/a/29552710/341994

So, by design, prepareForSegue happens before the new view controller has its view - or its outlets. Conversely, the first moment when its outlets are connected is its own viewDidLoad, which is later.

Your real mistake, though, is deeper. One view controller has no business setting or talking to another view controller's outlets and thus manipulating its interface. Instead, set things up so that the destination view controller has an ordinary property which you can set. In viewDidLoad, that view controller than checks that property, retrieves the value, and sets its own interface through its outlet.

So, to sum up: prepareForSegue is your chance to initialize the new view controller. But that's all. The new view controller will then later control its own view — as the name implies! And it will do this starting in its own viewDidLoad and later.

How to avoid returning an optional after throwing an exception?

You can use Swift assert(_:_file:line:) function as follows

assert(some condition, "Message to display if condition is false (optional)" )

If the condition is verified the app will continue running, otherwise it will terminate

Throwing on unwrapping nil optional

It looks ok, but it's even better with guard let instead of if let because it lets you use the unwrapped value in the main do block instead of having to work inside an if let branch. You can also use several catch branches to handle different error types.

do {

guard let value = mightHaveAValue else {
throw MyErrorType.BadTimes
}

// do stuff with value

} catch let error as MyErrorType {
// handle custom error
} catch let error as NSError {
// handle generic NSError
}

There is no automatic way to handle unwrapping optionals, you have to use one of the many known ways: if let, guard let, nil coalescing, etc.

How to avoid returning an optional after throwing an exception?

You can use Swift assert(_:_file:line:) function as follows

assert(some condition, "Message to display if condition is false (optional)" )

If the condition is verified the app will continue running, otherwise it will terminate

swift force-unwrapping exception not propagated

From the documentation:

Error Handling

Error handling is the process of responding to and recovering from
error conditions in your program. Swift provides first-class support
for throwing, catching, propagating, and manipulating recoverable
errors at runtime.

...

Representing and Throwing Errors

In Swift, errors are represented by values of types that conform to
the ErrorType protocol. This empty protocol indicates that a type can
be used for error handling.

(Note: ErrorType has been renamed to Error in Swift 3)

So with try/catch you handle Swift errors (values of types that conform to the ErrorType protocol) which are thrown.
This is completely unrelated to runtime errors and runtime exceptions
(and also unrelated to NSException from the Foundation library).

Note that the Swift documentation on error handling does not even use the
word "exception", with the only exception (!) in (emphasis mine) in:

NOTE

Error handling in Swift resembles exception handling in other
languages, with the use of the try, catch and throw keywords. Unlike
exception handling in many languages—including Objective-C—error
handling in Swift does not involve unwinding the call stack, a process
that can be computationally expensive. As such, the performance
characteristics of a throw statement are comparable to those of a
return statement.

The unwrapping of optionals which are nil does not throw a
Swift error (which could be propagated) and cannot be handled with
try.

You have to use the well-known techniques like
optional binding, optional chaining, checking against nil etc.

Swift app stops running after an error

I think you are overusing the ! (force unwrap) symbol here. It does not deal gracefully with nil values, in fact, it crashes.

I think what you might want to be doing here is

guard
let ps: Element = try? doc.getElementById("product-name"),
let ide = try? ps.text()
else {
print("error")
ide = ""
}
// ide is guaranteed to be valid here
...

Note how if you use try? you do not need to "catch" the error, it will simply return an optional value, nil if the call would raise an exception.


Alternatively you could simply

let ps: Element = try? doc.getElementById("product-name")
let ide = try? ps?.text()
// ide will be an optional value here

If you really don't want to guard/if let...



Related Topics



Leave a reply



Submit