check the variable is null right away

Hi ,


I use this below code ...


userProfile.login_date = memberData?["login_date"] as! String


The problem is if there is no value (I mean memberData?["login_date"] is null ) , the app falls down with error.


So I want to do this like, if memberData?["login_date"] is null, just do not input a value,

if there is a value, just put a value.


I can use "if" statement, but it seems like there is other simple way in swift ..


Could someone tell me how to do that ?


Thanks

Accepted Reply

Some suggestions…


If login_date property of userProfile is a String and you do not want to change its value when no date string is retrieved from the Optional Dictionary memberData:


if let date = memberData?["login_date"] as? String {
     userProfile.login_date = date
}



If login_date property of userProfile is a String and you want to set it to some default value when no date string is retrieved from the Optional Dictionary memberData:


userProfile.login_date = memberData?["login_date"] as? String ?? defaultValue



If login_date property of userProfile is an Optional String and you want to set it to nil when no date string can be retrieved from the Optional Dictionary memberData:


userProfile.login_date = memberData?["login_date"] as? String

Replies

Normal, because as! fails.


this should work (not tested):


let aDate = memberData?["login_date"] ?? ""
userProfile.login_date = aDate as String

'Thanks , Claude31 ^^


So could you tell me what '??' means .. .

Sorry for basic grammer question..


ps. I just found that is not working..

userProfile.login_date = aDate as String ---> "Any is not convertable to String" error..

and if I do 'userProfile.login_date = aDate as! String'

then error "Could not cast value of type 'NSNull' to 'NSString'" happened.. .

any one , any idea plz ..

?? is called nil coalescing operator :


let x = anOptionalString ?? "No String"


it tests if anOptionalString is non nil ; if so, it unwraps it ; otherwise, it assigns the second member to x


it is equivalent to

let x = anOptionalString != nil ? anOptionalString! : "No String"


For the error (sorry, I'm not yet on Swift 3), try :

let aDate = memberData?["login_date"] as? String ?? "" 
userProfile.login_date = aDate

There are a couple of things going on here. Let's go back to this:


memberData?["login_date"]


If memberData is a Dictionary (of type [String: Any], I would guess), then why are you using the optional chaining operator ("?"). The simple reference:


memberData ["login_date"]


already returns an optional (Any?), because that's how dictionaries work: you look up a key, and there may or may not be a value. By adding the "?" operator, you're changing the result type from Any? to Any??. That's why — via a series of bridging rules — you're ending up with the value of type NSNull (I think).


So, my guess is you want something like this:


userProfile.login_date = (memberData ["login_date"] as? String) ?? ""


However, keep in mind that you're dealing with three cases, not two:


1. The dictionary contains a date string.


2. The dictionary contains no entry for key "login_date".


3. The dictionary contains an entry for key "login_date", but it's not a String.


If you want to handle these properly, you really need to do the conversions in a different order:


userProfile.login_date = (memberData ["login_date"] ?? "") as! String


That is, a missing value defaults to "", but an incorrect value causes a deliberate program crash. (You can handle this error if you want, but if it's a "shouldn't happen" error, the recommended techique is to crash immediately.)

Some suggestions…


If login_date property of userProfile is a String and you do not want to change its value when no date string is retrieved from the Optional Dictionary memberData:


if let date = memberData?["login_date"] as? String {
     userProfile.login_date = date
}



If login_date property of userProfile is a String and you want to set it to some default value when no date string is retrieved from the Optional Dictionary memberData:


userProfile.login_date = memberData?["login_date"] as? String ?? defaultValue



If login_date property of userProfile is an Optional String and you want to set it to nil when no date string can be retrieved from the Optional Dictionary memberData:


userProfile.login_date = memberData?["login_date"] as? String

memberData?["login_date"]
would not even compile if memberData was a Dictionary, so I guess memberData is an Optional Dictionary. It may have been retrieved from a parent Dictionary, since stcocoa recently asked how to access a value from a dictionary nested inside a dictionary in thread How to access value of Dictionary in a Dictionary?

I expect you're right (and I normally try to check my assumptions and suggestions in a playground before posting, but there were too many unknowns in this case), but I think I'm still correct that the use of the optional chaining operator is going to add a level to optionality to the already-optional result of the dictionary subscript operator.


More importantly, if memberData is an optional, then it's (I believe) a code smell for the optional to have "escaped" from the site where it was obtained. The optional should have be resolved there. In the case where memberData is optional, not an error, and there's a whole series of decisions to be take that involve some complex consideration of its optionality and the optionality of its members, then it could be argued that it should continue as an optional dictionary (memberData?), but even then I would argue that life is easier if you clarify the situation with explicit "if let" and "guard let" statements.

"[...] but I think I'm still correct that the use of the optional chaining operator is going to add a level to optionality to the already-optional result of the dictionary subscript operator."


No, optional chaining doesn't add levels of optionality when you're trying to retrieve a type that's already optional. The result of key-subscripting a dictionary is an optional, anyway, so an optional chain won't make the result more optional.



"More importantly [...] but even then I would argue that life is easier if you clarify the situation with explicit "if let" and "guard let" statements."

Yes, I would typically code in that manner, but wanted to point out to you that the OP must have been using an optional dictionary since his optional chaining code did compile, although the program subsequently crashed when attempting to use the as! operator