4

I want to unwrap these 6 optional variables, and if they are null i want to give them a blank String value. This is so I can send these variables packaged into a parameters array that's sent to an API.

I'm still a beginner at Swift, and this is the only easiest way I have understood how to implement this, but the inner coder in me is saying this looks redundant and crappy as ****.

Can someone help me condense this or make it simpler?

    if let fbEmail = self.fbEmail {

    }else{
        self.fbEmail = ""
    }

    if let fbDob = self.fbDob {

    }else{
        self.fbDob = ""
    }

    if let fbGender = self.fbGender {

    }else{
        self.fbGender = ""
    }
    if let fbUserIp = self.fbUserIp {

    }else{
        self.fbUserIp = ""
    }
    if let fbFacebookId = self.fbFacebookId {

    }else{
        self.fbFacebookId = ""
    }
    if let fbFacebookAccessToken = self.fbFacebookAccessToken {

    }else{
        self.fbFacebookAccessToken = ""
    }
rmaddy
  • 314,917
  • 42
  • 532
  • 579
trixmasta
  • 233
  • 3
  • 14

2 Answers2

8

You can do that in exactly 6 lines of code:

self.fbEmail  = self.fbEmail  ?? ""
self.fbDob    = self.fbDob    ?? ""
self.fbGender = self.fbGender ?? ""
self.fbUserIp = self.fbUserIp ?? ""
self.fbFacebookId = self.fbFacebookId ?? ""
self.fbFacebookAccessToken = self.fbFacebookAccessToken ?? ""

Edit: what's up with the ?? syntax: It's a shortcut "if nil assign another value":

let c = a ?? b

will assign c = a if a != nil, otherwise c = b.

Code Different
  • 90,614
  • 16
  • 144
  • 163
  • Could you please explain the "??" syntax and what's exactly going on here? – trixmasta Oct 02 '15 at 01:49
  • After a second reading of your code, I'm not sure what you were trying to do. Do you want to assign an empty string to `self.fbEmail` when it is nil or trying to assign its value to a local variable? – Code Different Oct 02 '15 at 01:55
  • I'm trying to assign an empty string to self.fbEmail when it's nil – trixmasta Oct 02 '15 at 01:57
  • Thank you!! This is exactly what i was looking for. – trixmasta Oct 02 '15 at 01:58
  • 1
    Slight correction: `let c = a ?? b` will assign `c = a!` if `a != nil`, otherwise `c = b`. The unwrap is important. – vacawama Oct 02 '15 at 01:59
  • 1
    Did not know that operator. So elegant! – R Menke Oct 02 '15 at 02:09
  • I myself prefer to define a helper operator, `??=`, which does `lhs = lhs ?? rhs`. – jtbandes Oct 02 '15 at 02:25
  • The `??` operator is know as the [Nil Coalescing Operator in the Swift Documentation](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID60). – Maic López Sáenz Oct 02 '15 at 04:03
4

You can unwrap more than one at a time. But if you do, you will have no way of knowing which one is nil. You will only know that either some are nil or none are.

Aside from that do they all need to be optional? Can't you init them with the default values you are giving them when they are nil?


Snippets:

Just avoid the issue altogether.

// just init with a default value without them being an optional
var fbEmail : String = ""
var fbDob : String = ""

Replace checking for nil with .isEmpty

var string : String = ""

string.isEmpty // returns true

string = "SomeString"

string.isEmpty // returns false

Optionals with starting values.

// init wit default values while still optional
var fbEmail : String? = ""
var fbDob : String? = ""

Unwrap more than one at a time.

if let unwrfbEmail = fbEmail, let unwrfbDob = fbDob {
    // stuff available here
} else {
    // handle the error
}

guard let unwrfbEmail = fbEmail, let unwrfbDob = fbDob else {
    // put return/break here and handle the error
}
// stuff available here

A container for all values. They are optionals but when set to nil they will reset to a default value. You can also declare them as forced unwrapped optionals !. Or unwrap them all at once with a method found above. Obviously copy paste and alter the didSet to all variables.

// container stuct that uses didSet to avoid nil and reset to default values
struct container {

    var fbEmail : String? = "" {
        didSet {
            if fbEmail == nil {
                fbEmail = ""
            }
        }
    }
    var fbDob : String? = ""
    var fbGender : String? = ""
    var fbUserIp : String? = ""
    var fbFacebookId : String? = ""
    var fbFacebookAccessToken : String? = ""

}
R Menke
  • 8,183
  • 4
  • 35
  • 63
  • Agreed; I think optionals should only be used for variables that don't have a meaningful default value to initialize them to, or otherwise need to be able to flag the state of "not being set". – Nicolas Miari Oct 02 '15 at 01:30
  • @NicolasMiari Agree completely, with you agreeing with me and with your other points :) They could be needed because the function that is used to fetch the value might return nil. Using didSet in that case to reset to default is a nice fix. – R Menke Oct 02 '15 at 01:34
  • This was a great and very comprehensive answer! Thank you R Menke. I actually went through the solutions of just declaring an initial "" blank value, however that would interfere with other functions I have that check if the variable is optional or not. For example, fbEmail is an optional, and I can give it "" by default, but then doesEmailExist() function wouldn't work correctly because it would think a blank string means an email exists. So essentially, I don't think any of these solutions work :( Ps. I tried the "unwrap more than 1 at a time", i need to figure if certain vars aren't nil :/ – trixmasta Oct 02 '15 at 01:51
  • 1
    replace checking for nil with `.isEmpty` – R Menke Oct 02 '15 at 01:55
  • ooooh now that will work, but kinda defeats the purpose of making it an optional in the first place, right? – trixmasta Oct 02 '15 at 01:56
  • exactly why I am suggesting it ;) – R Menke Oct 02 '15 at 01:57