简体   繁体   English

下标用法模棱两可?

[英]Ambiguous use of subscript?

I can make a Facebook SDK Graph Request to get a user's likes, but I'm having trouble taking the returned values and storing one of the keys in an array of Strings. 我可以发出Facebook SDK Graph请求来获得用户的喜欢,但是我在获取返回值并将键之一存储在字符串数组中时遇到了麻烦。 The request returns an NSDictionary of keys/values. 该请求返回键/值的NSDictionary。 Then, using objectForKey I can get the data key which returns what I want: the id and name of the "liked" page on Facebook. 然后,使用objectForKey我可以获取返回我想要的data密钥:Facebook上“喜欢”页面的ID和名称。

Data returns elements like this: 数据返回如下元素:

{
        id = 486379781543416;
        name = "Star Wars Movies";
    },

I specifically want only the "name" of all of these objects and to throw them into an array [String] . 我专门只希望所有这些对象的“名称”并将它们放入数组[String] I tried to loop through the objects but I'm getting error ambiguous use of subscript . 我试图遍历对象,但是ambiguous use of subscript出现错误ambiguous use of subscript Here's the relevant code: 以下是相关代码:

request.startWithCompletionHandler{(connection:FBSDKGraphRequestConnection!, result:AnyObject!, error:NSError!) -> Void in
            let resultdict = result as! NSDictionary     
            let likes = resultdict.objectForKey("data") as! NSArray
            print("Found \(likes.count) likes")
            print(likes)

            for object in likes{

                let name = object["name"] as! String //error: ambiguous use of subsript
                print(name)
            }

        }

After doing some research it looks like the issue is with the NSArray and that I should instead use Swift data types. 经过一些研究后,看起来好像是NSArray存在问题,我应该改用Swift数据类型。 I tried casting it to a Swift array but I got different errors. 我尝试将其强制转换为Swift数组,但遇到了不同的错误。

What's the best way to handle this error? 处理此错误的最佳方法是什么?

Thanks! 谢谢!

update: Here is what the facebook API request returns: 更新:这是facebook API请求返回的内容:

{
    data =     (
                {
            id = 111276025563005;
            name = "Star Wars (film)";
        },
                {
            id = 115061321839188;
            name = "Return of the Jedi";
        }
    );
    paging =     {
        cursors =         {
            after = MTE1MDYxMzIxODM5MTg4;
            before = Mjc0NzYzODk2MTg4NjY5;
        };
        next = "https://graph.facebook.com/v2.5/10155262562690368/likes?access_token=<redacted>";
    };
}

You should always use the native Swift collection types wherever possible as NSArray and NSDictionary are really type-inspecific, and therefore can easily trigger "ambiguous use of subscript" errors. 您应该始终尽可能使用本机Swift集合类型,因为NSArrayNSDictionary确实是类型无关的,因此可以轻松触发“模棱两可的使用”错误。

You'll also want to avoid force down-casting, in case you receive data that's in the wrong format, or no data at all. 您还希望避免强制向下广播,以防接收格式错误的数据或根本没有数据。 This situation would be more elegantly handled with a guard , in order to prevent a crash. 为了防止撞车,这种情况将由guard更好地处理。 If your program depends on the force down-casting succeeding, and therefore should crash – then you can always call fatalError in the guard, with a descriptive error message in order to assist you in debugging the problem. 如果您的程序依赖于强制向下转换的成功,因此应该崩溃–那么您可以随时在防护中调用fatalError并提供描述性错误消息,以帮助您调试问题。

If I understand your data structure correctly, the request returns an AnyObject that should be a [String:AnyObject] (A dictionary of strings to any objects). 如果我正确理解了您的数据结构,则请求将返回一个AnyObject ,该对象应为[String:AnyObject] (任何对象的字符串字典)。 In the case of the "data" key, the AnyObject value is then a [[String:AnyObject]] (An array of dictionaries of strings to any objects). 如果使用"data"键,则AnyObjectAnyObject [[String:AnyObject]] (任何对象的字符串字典的数组)。

Therefore you'll want to do your casting in two stages. 因此,您需要分两个阶段进行转换。 First, using a conditional downcast on your result to cast it as a [String:AnyObject] . 首先,对result使用条件[String:AnyObject]将其[String:AnyObject]转换为[String:AnyObject] If this fails, then the else clause of the guard will be executed and the code will return. 如果失败,则将执行保护的else子句,并返回代码。 You'll then want to get out your "data" value (your 'likes' array), and conditionally downcast it to a [[String:AnyObject]] . 然后,您将希望获取"data"值(您的“喜欢”数组),并有条件地将其转换为[[String:AnyObject]] Both of these statements will handle the possibility of resultDict or resultDict["data"] being nil . 这两个语句都将处理resultDictresultDict["data"]nil的可能性。

guard let resultDict = result as? [String:AnyObject] else {return}
guard let likes = resultDict["data"] as? [[String:AnyObject]] else {return}

You can put whatever error handling logic you want in the brackets of these statements to handle cases in which the results dictionary doesn't exist, was the wrong format, or there wasn't a 'likes' array in it. 您可以将所需的任何错误处理逻辑放在这些语句的括号中,以处理结果字典不存在,格式错误或其中没有“喜欢”数组的情况。

You can then get an array of 'like' names through using flatMap . 然后,您可以使用flatMap获得一个“喜欢”名称的数组。

let likeNames = likes.flatMap{$0["name"] as? String}

This will create an array of the like names of each dictionary – if the like names don't exist or aren't strings, then they won't be added. 这将创建一个由每个字典的相似名称组成的数组–如果相似名称不存在或不是字符串,则不会添加它们。 Because the compiler knows for certain that likes is a [[String:AnyObject]] – there's no ambiguity in subscripting its elements. 因为编译器肯定知道likes[[String:AnyObject]] –在其元素下标没有任何歧义。

If you want a more general approach such as you're doing in your question, you can use a guard statement within a for loop. 如果您想要一个更通用的方法(例如您在问题中所做的事情),则可以在for循环中使用guard语句。

for object in likes {
    guard let name = object["name"] as? String else {continue}
    print(name)
}

Again, you can put whatever error handling you wish in the brackets of the guard. 同样,您可以将所需的任何错误处理放入防护罩中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM