cast NSString! to String in swift

35,588

decodeObjectForKey returns an optional AnyObject?, so you have to guard your code against possible nil values. Using a cast to a forced unwrapped doesn't sound safe.

I am unable to reproduce the error (so the problem could be somewhere else in your code), but this is how I would approach when initializing the name property:

    var tempName = aDecoder.decodeObjectForKey("name") as? String
    if let tempName = tempName {
        self.name = tempName
    } else {
        self.name = "some initial value"
    }

Note the usage of the optional downcasting as?, which always produce a result (nil or a valid type value) as opposed to as NSString!, which triggers an exception if the downcast is not possible (for instance if you are expecting a string, but it's an int instead).

That code would also allow you to better debugging - if tempName is nil, then either the key doesn't exist or the corresponding value is of a different type.

Share:
35,588
Arash
Author by

Arash

Updated on September 21, 2020

Comments

  • Arash
    Arash over 3 years

    I have a instance variable name in String

    var name: String
    

    My class implements the NSCoding protocol. So for name I had

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.name, forKey: kName)
    }
    
    required init(coder aDecoder: NSCoder) {
        self.name = aDecoder.decodeObjectForKey(kName) as String  // CRASH HERE
    }
    

    Result? I was getting a run time crash during initiation with decoder. I changed init to this:

    var temp = aDecoder.decodeObjectForKey(kName) as NSString!
    self.name = aDecoder.decodeObjectForKey(kName) as String
    

    and realised the value temp is holding the right NSString value. so I thought the line below is going to fix it but it issues a linker error:

    self.name = aDecoder.decodeObjectForKey(kName) as NSString!
    

    the questions is how to take the temp and put it into name?

  • jlehr
    jlehr over 9 years
    You can replace your if/else logic with an expression using Swift's nil-coalescing operator as follows: self.name = tempName ?? "some initial value"
  • Antonio
    Antonio over 9 years
    Yeah good advice. I didn't use it just for clarity, but I didn't even mention :)
  • Arash
    Arash over 9 years
    thanks for the answer. but the problem seem to be to cast from NSString! to String.
  • Arash
    Arash over 9 years
    thanks for the answer. The problem is that the decodeObjectForKey seem to return an NSString that is never cartable to String. So the code you suggested never assigns a value to name property.
  • Antonio
    Antonio over 9 years
    Never heard of a NSString that cannot be cast to String. Try saving what decodeObjectForKey returns to a AnyObject? variable, then assign to tempName via downcast, and use the debugger to step through the lines and see what's going on - hope that can help you figuring out
  • HenryRootTwo
    HenryRootTwo over 9 years
    assert halts execution, last line will never be called, but what did you need it for?
  • Andy Dent
    Andy Dent almost 9 years
    assert only halts execution in debug builds - it's the same semantics as the C version. See the very cool blog post about how they built this developer.apple.com/swift/blog/?id=4