我是Swift的新手,目前正在玩Stickers。
我有一个具有以下结构的JSON文件:
{
"stickers": [{
"filename": "happy_face",
"description": "Happy Face",
"premium": "false",
"categories": ["blue", "green", "red"],
"genders": ["male", "female"]
},{
"filename": "sad_face",
"description": "Sad Face",
"premium": "false",
"categories": ["blue", "green", "red", "yellow"],
"genders": ["male"]
}]
}
贴纸将具有相同的文件名,但会根据它们的类别和性别分成文件夹。
我可以很好地读取JSON数据。我的问题是,当我尝试利用JSON数据时。
我的目标是根据标签的类别将其分开,标签的种类可能会有所不同,用户稍后将可以切换类别,并显示正确的标签。
let stickerPack = StickerPack.load()
let allStickers = stickerPack!["stickers"] as? [[AnyHashable : Any]]
func getStickersWithCategory(category: String){
var stickers = [AnyObject]()
for sticker in allStickers! {
let cat = sticker["categories"] as? [String]
for item in cat! {
if item.contains(category){
stickers.append(sticker)
}
}
}
}
结果是
“参数类型'[AnyHashable:Any]'不符合预期的类型'AnyObject'”
有人能指出我正确的方向吗?这个JSON结构可能吗?还是将每个类别和性别分别设置为不同的结构更好?这将导致很多重复。但是也许我通过尝试以这种方式保持JSON结构来制造更多问题。
感谢所有帮助!
答案 0 :(得分:0)
问题在于您将allStickers
声明为let allStickers = stickerPack!["stickers"] as? [[AnyHashable : Any]]
,这意味着其类型将为[[AnyHashable:Any]]?
或Array<Dictionary<AnyHashable:Any>>
。当您遍历for sticker in allStickers!
中的数组时,sticker
的类型将为Dictionary<AnyHashable:Any>
。 Dictionary
是一个结构,因此不符合AnyObject
,因此您不能向sticker
添加stickers
,AnyObjects
被声明为{{1}的数组}。
因此,将var stickers = [AnyObject]()
更改为var stickers = [Any]()
,或更具体地说将var stickers = [[AnyHashable:Any]]()
应该可以解决您的问题。
func getStickersWithCategory(category: String){
var stickers = [[AnyHashable:Any]]()
for sticker in allStickers! {
let cat = sticker["categories"] as? [String]
for item in cat! {
if item.contains(category){
stickers.append(sticker)
}
}
}
}
在处理JSON时,建议您在Swift 4中使用Codable
。
答案 1 :(得分:0)
更具体的类型,可以避免这种错误。
此JSON数组为[[String:Any]]
,从不 AnyHashable
,因为键必须是字符串
let allStickers = stickerPack!["stickers"] as? [[String:Any]]
stickers
是相同的类型,从不是包含AnyObject
的类型。所有JSON类型都是值类型(Any
)。
var stickers = [[String:Any]]()
您可以过滤数组 swiftier ,建议安全地拆开所有可选项
if let stickerPack = StickerPack.load(),
let allStickers = stickerPack["stickers"] as? [[String:Any]] {
stickers = allStickers.filter({ (sticker) -> Bool in
guard let categories = sticker["categories"] as? [String] else { return false }
return categories.contains(category)
})
...