3 Replies
      Latest reply: Oct 6, 2016 5:09 AM by eskimo RSS
      Wellington Level 1 Level 1 (0 points)

        In Swift 2.x, the following code would fail to compile:

        let anArray = NSMutableArray()
        let something = callSomethingThatReturnsAnOptionalObject()
        anArray.addObject(something) << error "value of optional type 'XXX?' not unwrapped."
        

         

        Whereas in Swift 3 the equivalent happily compiles:

        let anArray = NSMutableArray()
        let something = callSomethingThatReturnsAnOptionalObject()
        anArray.add(something)
        

         

        and in the case where 'something' end up as a nil optional the code will happily continue until some Obj-C code tries to use that 'nil' optional. In my case it was NSCoder trying to encode the array and failing when it hit the offending item.

         

        This seems really dangerous, why was it allowed to happen. Seems like a regression to me?

         

        (I haven't checked, but I suspect other NSMutableXXX containers can suffer the same issue)

        • Re: NSMutableArray much less safe in Swift 3?
          ahltorp Level 3 Level 3 (410 points)

          In Swift 2, NSMutableArray stored things of type AnyObject, but in Swift 3 the type is changed to Any. This means that optionals, which are enums, can be stored.

           

          Optionals were bridged to an opaque object that was not accessible in Objective-C, and that is probably still the case, but a proposal has been accepted (SE-0140) that changes this:

          Converting an Optional<T> to an Any should raise a warning unless the conversion is made explicit. When an Optional<T> value does end up in an Any, and gets bridged to an Objective-C object, if it contains some value, that value should be bridged; otherwise, NSNull or another sentinel object should be used.

           

          This was accepted a few weeks ago, and I don't know when that will be implemented and shipped in Xcode.

          • Re: NSMutableArray much less safe in Swift 3?
            eskimo Apple Staff Apple Staff (7,530 points)

            (I haven't checked, but I suspect other NSMutableXXX containers can suffer the same issue)

            Indeed.  I generally avoid this issue by working in ‘Swift space’ as much as possible.  That way I get strict type checking right up until the last minute.  To continue your example, I’d write this:

            var anArray: [Foo] = []
            let something = callSomethingThatReturnsAnOptionalObject()
            anArray.append(something)
            coder.encode(anArray as NSArray)
            

            which fails to compile because append(_:) won’t accept a Foo?.

            This doesn’t work all the time (for example, if the array is heterogeneous) but it’s helpful in many cases.

            Share and Enjoy

            Quinn “The Eskimo!”
            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
            let myEmail = "eskimo" + "1" + "@apple.com"