Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Displaying Data with Table Views in Swift 2 Enhancing the Networking Stack Conforming to Endpoint

Keenan Turner
Keenan Turner
6,270 Points

Conforming To Endpoint Course: Why is Swift 3 compiler making me cast the values in the dictionary as "AnyObject"?

I've noticed this happen before, but still am unsure why Swift 3 wants to me be more specific and cast objects to their implied type. I assume it's in the new changes, but would love to hear other's thought.

Here is my code, and it looks similar to the instructor's code:

var parameters: [String : AnyObject] {
            switch self {
            case .Search(clientID: let clientID, clientSecret: let clientSecret, coordinate: let coordinate, category: let category, query: let query, searchRadius: let searchRadius, limit: let limit):

                var parameters: [String: AnyObject] = [
                    ParameterKeys.clientID: clientID,
                    ParameterKeys.clientSecret: clientSecret,
                    ParameterKeys.version: DefaultValues.version,
                    ParameterKeys.location: coordinate.description,
                    ParameterKeys.category: category.description
                ]

                if let searchRadius = searchRadius {
                    parameters[ParameterKeys.searchRadius] = searchRadius
                } else {
                    parameters[ParameterKeys.searchRadius] = DefaultValues.searchRadius
                }

                if let limit = limit {
                    parameters[ParameterKeys.limit] = limit
                } else {
                    parameters[ParameterKeys.limit] = DefaultValues.limit
                }

                if let query = query {
                    parameters[ParameterKeys.query] = query
                }

                return parameters

            }
        }

And the compiler won't stop screaming until my code is like this:

var parameters: [String : AnyObject] {
            switch self {
            case .Search(clientID: let clientID, clientSecret: let clientSecret, coordinate: let coordinate, category: let category, query: let query, searchRadius: let searchRadius, limit: let limit):

                var parameters: [String: AnyObject] = [
                    ParameterKeys.clientID: clientID as AnyObject,
                    ParameterKeys.clientSecret: clientSecret as AnyObject,
                    ParameterKeys.version: DefaultValues.version as AnyObject,
                    ParameterKeys.location: coordinate.description as AnyObject,
                    ParameterKeys.category: category.description as AnyObject
                ]

                if let searchRadius = searchRadius {
                    parameters[ParameterKeys.searchRadius] = searchRadius as AnyObject?
                } else {
                    parameters[ParameterKeys.searchRadius] = DefaultValues.searchRadius as AnyObject?
                }

                if let limit = limit {
                    parameters[ParameterKeys.limit] = limit as AnyObject?
                } else {
                    parameters[ParameterKeys.limit] = DefaultValues.limit as AnyObject?
                }

                if let query = query {
                    parameters[ParameterKeys.query] = query as AnyObject?
                }

                return parameters

            }
        }

Would love some help on understanding why, thanks!

2 Answers

Keenan Turner
Keenan Turner
6,270 Points

Thanks Jeff Ripke !

For those that have this question and want the answer for the official documents / stackoverflow:

"The removal of the implicit bridging mechanisms was accepted in the following Swift evolution proposal, to be implemented for Swift 3

SE-0072: Fully eliminate implicit bridging conversions from Swift Previously, implicit conversions were available from some Swift native types to associated Objective-C types (Swift types conforming to private protocol _ObjectiveCBridgeable, e.g. natively Int, String, )

For this reason, we decided to make a compromise. We would require explicit bridging casts when converting from a bridged Objective-C type to its associated Swift value type (E.g., NSString -> String), but not the other way around.

... [From SE-0072] With Swift 3, such implicit conversion mechanisms will no longer be available.

With the introduction of Objective-C generics last year, along with all of the awesome improvements to API importing happening for Swift 3, I think it’s time that we take another look at completing this work.

...

I propose that we fully eliminate implicit bridging conversions in Swift 3. This would mean that some users might have to introduce more explicit casts in their code, but we would remove another special case from Swift's type system and be able to further simplify the compiler.

...

Code that previously relied on implicit conversions between Swift value types and their associated bridged Objective-C type will now require a manual coercion via an as cast. Finally, the release notes for Xcode 8 beta 6 (login required) states that this proposal has now been implemented for beta 6:

New in Xcode 8 beta 6 - Swift Compiler: Swift Language

...

Bridging conversions are no longer implicit. The conversion from a Swift value type to its corresponding object can be forced with as. For example: string as NSString. Any Swift value can also be converted to its boxed id representation with as AnyObject. (SE-0072) W.r.t. new "boxed id" allowing explicit conversion for any Swift value to AnyObject, see e.g. the following thread:

AnyObject not working in Xcode8 beta6?"

Hi guys, incase you need any further guidance, I found this Stack Overflow post really helpful:

http://stackoverflow.com/questions/38701044/value-of-type-string-does-not-conform-to-expected-dictionary-value-type-anyob

:)