1

in Swift3 I had code like this

var result: String = ""
...
result = try db?.scalar(q) as! String

of course that's crap and often crashes.

1) the whole thing can be nil

2) since it's an optional binding, it may not be a String

This works pretty reliably

if let sc = try db?.scalar(q) {
    print("good news, that is not nil!")
    if sc is String {
        print("good news, it is a String!")
        result = sc as! String
    } else {
        print("bizarrely, it was not a String. but at least we didn't crash")
        result = ""
    }
else {
    print ("the whole thing is NIL!  wth.")
    result = ""
}

(Unless I forgot something.)

But it seems very nonswifty and long. Is there a better way? If not better, shorter?

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
Fattie
  • 27,874
  • 70
  • 431
  • 719
  • BTW, it's probably best to unwrap your `db` early on in a `guard let` statement, handle the `nil` case, and then not have to worry about the chance of it being `nil` in the rest of the code – Alexander Dec 20 '16 at 20:21
  • funny you mention that. since it's a `var db:Connection?` (in a globally-accessed class), that in SQLite.swift, I don't know how to make it a non-optional type - because I don't know how to set it to some sort of default (like "0") when that class is initialized. and the SQLite.swift code that initializes the database (ie "db". that `Connection`) does not run immediately. so the damn thing has to be optional everywhere it appears in the whole app. – Fattie Dec 20 '16 at 21:10
  • It doesn't need to be an optional of it's initialized either inline (which can be a constant expression, as you said, or the result of running a closure), or if it's initialized in the class' initializer. – Alexander Dec 20 '16 at 21:11
  • Usually you you should try to structure your app to avoid that, whenever possible. Otherwise, I would use an implicitly unwrapped optional. – Alexander Dec 20 '16 at 21:23
  • var db: Connection! – Alexander Dec 20 '16 at 21:24
  • http://stackoverflow.com/questions/24006975/why-create-implicitly-unwrapped-optionals – Alexander Dec 20 '16 at 21:25
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/131092/discussion-between-alexander-and-joe-blow). – Alexander Dec 20 '16 at 21:26
  • Comments are not for extended discussion. I've moved this comment section to chat. – Alexander Dec 20 '16 at 21:26
  • I made a related question to clarify this issue, thanks for raising it @Alexander ! http://stackoverflow.com/q/41251580/294884 – Fattie Dec 20 '16 at 21:32

1 Answers1

1
if let sc = try db?.scalar(q) as? String { ...
    print("good news, that is not nil!")
    print("good news, it is a String!")
    result = sc
else {
    print("bizarrely, it was not a String. but at least we didn't crash")
    result = ""
}

If all you're trying to get is the String value (if non-nil, and correctly types as String) or "", just do:

let result = try db?.scalar(q) as? String ?? ""
Alexander
  • 59,041
  • 12
  • 98
  • 151
  • wait my friend - does that handle the case of the WHOLE THING being nil? The whole binding can be optional. This >>db?.scalar(q)<< is an optional binding; it can be nil. – Fattie Dec 20 '16 at 20:10
  • Yeah, the nil propagates forward, because using `as? String` on `nil` gives `nil` – Alexander Dec 20 '16 at 20:11
  • Fantastic. understood. I guess that's the canonical answer cheers :) – Fattie Dec 20 '16 at 20:21