iosswiftdictionarysnapchatswift-dictionary

Error: Type [AnyHashable: Any]? has no subscript members (Swift)


I am trying to use Snapchat's Login Kit to allow users to login with Snapchat, but their documentation gives me an error.

Copying the documentation gets me a "Type '[AnyHashable : Any]?' has no subscript members. The error happens on the "let data = " line. If I force unwrap resources, then the error moves to the next line

let graphQLQuery = "{me{displayName, bitmoji{avatar}, externalId}}"
let variables = ["page": "bitmoji"]

SCSDKLoginClient.fetchUserData(withQuery: graphQLQuery, variables: variables, success: { (resources: [AnyHashable: Any]?) in
    let data = resources["data"] //error here
    let me = data["me"]
    let displayName = me["displayName"]
    let bitmoji = me["bitmoji"]
    let bitmojiAvatarUrl = bitmoji["avatar"]
}, failure: { (error: Error?, isUserLoggedOut: Bool) in
    // handle error
})

If I unwrap data resources and data, then the error moves to the line where I try to set me = data["me"] (error = "Type Any has no subscript members"). Then if I try to unwrap me, the error remains.

ex:

let graphQLQuery = "{me{displayName, bitmoji{avatar}, externalId}}"

let variables = ["page": "bitmoji"]

    SCSDKLoginClient.fetchUserData(withQuery: graphQLQuery, variables: variables, success: { (resources: [AnyHashable: Any]?) in
        guard let response = resources else { return }
        guard let data = response["data"] else { return }
        print(data)
        let me = data["me"] // error here
        let displayName = me["displayName"]
        let bitmoji = me["bitmoji"]
        let bitmojiAvatarUrl = bitmoji["avatar"]
    }, failure: { (error: Error?, isUserLoggedOut: Bool) in
        // handle error
    })

Printing out data returns:

{
    me =     {
        bitmoji =         {
            avatar = "{URL}";
        };
        displayName = "{NAME}";
        externalId = "{ID}";
    };
}

Solution

  • You have to tell the compiler the static collection types because the compiler wants to prove the subscription ability.

    if let data = resources["data"] as? [String:Any],
       let me = data["me"] as? [String:Any] {
          let displayName = me["displayName"] as! String
          if let bitmoji = me["bitmoji"] as? [String:Any] {
             let bitmojiAvatarUrl = bitmoji["avatar"] as! String
          }
    }