我在Swift 3中做了以下功能:
func parseJSON() {
var JsonResult: NSMutableArray = NSMutableArray()
do {
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
} catch let error as NSError {
print(error)
}
var jsonElement:NSDictionary=NSDictionary()
let locations: NSMutableArray = NSMutableArray()
for i in 0 ..< JsonResult.count
{
jsonElement = JsonResult[i] as! NSDictionary
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.add(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
当我从另一个方法调用此函数时,我收到以下错误:
无法将'__NSArrayI'(0x105d4fc08)类型的值转换为'NSMutableArray'(0x105d4fcd0)。
它指向我这里的元素:
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
使用SIGBRT退出的地方..
我错过了什么?
答案 0 :(得分:1)
您正在尝试将NSArray转换为NSMutable数组,这是警告所抱怨的内容。
获取它为您提供的数组,然后将其转换为可变数组。
let jsonArray = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
jsonResult = jsonArray.mutableCopy() as! NSMutableArray
不相关,但您可能还希望为JsonResult使用小写值以符合正常的iOS样式指南。它应该是jsonResult。
答案 1 :(得分:1)
改善代码的另一种方法:
您没有改变JsonResult
,因此您无需将其声明为NSMutableArray
:
var JsonResult = NSArray()
do {
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
}
以及改善代码的一些步骤......
enum MyError: Error {
case NotArrayOfDict
}
func parseJSON() {
do {
guard let jsonResult = try JSONSerialization.jsonObject(with: self.data as Data) as? [[String: Any]] else {
throw MyError.NotArrayOfDict
}
let locations: NSMutableArray = NSMutableArray()
for jsonElement in jsonResult {
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.add(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
} catch let error {
print(error)
}
}
as!
施放有时会使您的应用崩溃,只有当您100%确保结果安全地转换为该类型时才使用它。如果不是,请使用带as?
的guard-let更安全。
尽可能使用Swift类型而不是NSSomething
。
不需要指定.allowFragments
,因为您希望将结果作为数组。
如果您可以修改代码的其他部分,则可以将代码编写为:
func parseJSON() {
do {
//If `self.data` was declared as `Data`, you would have no need to use `as Data`.
guard let jsonResult = try JSONSerialization.jsonObject(with: self.data) as? [[String: Any]] else {
throw MyError.NotArrayOfDict
}
var locations: [Parsexml] = [] //<-Use Swift Array
for jsonElement in jsonResult {
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.append(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
} catch let error {
print(error)
}
}