Casting NSDictionary as Dictionary Swift

2019-07-09 20:08发布

I've seen this solved in other questions - but I think that because this NSDictionary is accessed via subscript it's throwing some errors.

func pickRandomRecipe(arrayOfRecipes: NSArray) -> Dictionary<String,Any> {
let randomRecipeIndex = Int(arc4random_uniform(UInt32(arrayOfRecipes.count)))

//Could not cast value of type '__NSDictionaryI' (0x7fbfc4ce0208) to 'Swift.Dictionary<Swift.String, protocol<>>' (0x7fbfc4e44358)
let randomRecipe: Dictionary = arrayOfRecipes[randomRecipeIndex] as! Dictionary<String,Any>
return randomRecipe
}

2条回答
兄弟一词,经得起流年.
2楼-- · 2019-07-09 21:07

In this case NSDictionary can only be casted to [String: NSObject]. If you want it to be of type [String : Any] you have to make a separate Dictionary:

var dict = [String : Any]()
for (key, value) in randomRecipe {
    dict[key] = value
}
查看更多
做自己的国王
3楼-- · 2019-07-09 21:10

NSDictionary should be bridged to [NSCopying: AnyObject] or in your case [String: AnyObject], rather than using Any (since that's a Swift-only construct).

But I would recommend not using NSDictionary at all. You could define your function as

typealias Recipe = [String: AnyObject] // or some other Recipe class

func pickRandomRecipe(recipes: [Recipe]) -> Recipe? {
    if recipes.isEmpty { return nil }
    let index = Int(arc4random_uniform(UInt32(recipes.count)))
    return recipes[index]
}

Or perhaps even better:

extension Array {
    func randomChoice() -> Element? {
        if isEmpty { return nil }
        return self[Int(arc4random_uniform(UInt32(count)))]
    }
}

if let recipe = recipes.randomChoice() {
    // ...
}
查看更多
登录 后发表回答