我从生成json数组的php脚本中提取数据。 iOS更新后,我的jsonserialization崩溃了应用程序。 json应该根据jsonformatter.org和freeformatter.com/json-validator.html(符合RFC4627)很好地形成。 这是代码。非常感谢任何帮助!
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 = LocationModel()
//the following insures none of the JsonElement values are nil through optional binding
if let id = jsonElement["id"] as? String,
let oprettelsesdato = jsonElement["oprettelsesdato"] as? String,
let overskrift = jsonElement["overskrift"] as? String,
let address = jsonElement["address"] as? String,
let intro = jsonElement["intro"] as? String,
let email = jsonElement["email"] as? String,
let tlf = jsonElement["tlf"] as? String,
let annonce = jsonElement["annonce"] as? String,
let journalnr = jsonElement["journal"] as? String
{
location.id = id
location.oprettelsesdato = oprettelsesdato
location.overskrift = overskrift
location.address = address
location.intro = intro
location.email = email
location.tlf = tlf
location.annonce = annonce
location.journalnr = journalnr
}
locations.add(location)
}
DispatchQueue.main.async(execute: { () -> Void in
//print("Check home")
self.delegate.itemsDownloaded(locations)
})
}
崩溃日志:
objc[1285]: Class PLBuildVersion is implemented in both /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/AssetsLibraryServices.framework/AssetsLibraryServices (0x11799a998) and /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/PrivateFrameworks/PhotoLibraryServices.framework/PhotoLibraryServices (0x1177bc880). One of the two will be used. Which one is undefined.
Could not cast value of type '__NSArrayI' (0x105f1ed88) to 'NSMutableArray' (0x105f1ee50).
更新 我现在使用vadians解决方案,但是,我使用self.delegate.itemsDownloaded(位置为NSArray)而不是self.delegate.itemsDownloaded(位置)。
然而,所有jsonElements现在都是零。它获得了数组中正确数量的元素,但是如果我打印它,则所有值都是nil:
(
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil",
"id: nil, oprettelsesdato: nil, overskrift: nil, address: nil, journalnr: nil"
)
这是我尝试检索数据的地方。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item: LocationModel = feedItems[indexPath.row] as! LocationModel
let cellIdentifier: String = "BasicCell"
let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
//myCell.detailTextLabel!.text = item.oprettelsesdato
myCell.textLabel!.text = item.overskrift
myCell.textLabel!.leadingAnchor.constraint(equalTo: myCell.leadingAnchor).isActive = true
myCell.textLabel!.topAnchor.constraint(equalTo: myCell.topAnchor).isActive = true
myCell.textLabel!.heightAnchor.constraint(equalTo: myCell.heightAnchor,
multiplier: 1.0).isActive = true
myCell.textLabel!.widthAnchor.constraint(equalTo: myCell.heightAnchor,
multiplier: 0.8).isActive = true
//print(item.id) <-returns nil
//print(item.oprettelsesdato) <-returns nil
//print(item.overskrift) <-returns nil
extralabel!.text = item.oprettelsesdato // <-This is where the error is thrown
extralabel!.textColor = UIColor.white
myCell.contentView.addSubview(extralabel!)
//some more stuff...
}
错误:
fatal error: unexpectedly found nil while unwrapping an Optional value
不确定出了什么问题。有什么建议吗?
答案 0 :(得分:3)
请允许我重复我的评论:
NSMutable...
集合类型。它们与Swift集合类型无关并导致所有问题。
var
关键字使任何Swift对象都可变,非常容易使用。除此之外,您的代码中的接收数组根本没有变异。
可悲的是,建议NSMutable...
的半知识教程永远不会消亡:/
在Swift 3中
[String:Any]
[[String:Any]]
或[Any]
由于JSON对象应该是一个数组.allowframents
,因此很无用。
所以:
func parseJSON() {
var jsonResult = [[String:Any]]()
do{
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:[]) as! [[String:Any]]
} catch {
print(error)
return
}
var locations = [LocationModel]()
for jsonElement in jsonResult { // no ugly C-style index based loops!
let location = LocationModel()
//the following insures none of the JsonElement values are nil through optional binding
if let id = jsonElement["id"] as? String,
let oprettelsesdato = jsonElement["oprettelsesdato"] as? String,
let overskrift = jsonElement["overskrift"] as? String,
let address = jsonElement["address"] as? String,
let intro = jsonElement["intro"] as? String,
let email = jsonElement["email"] as? String,
let tlf = jsonElement["tlf"] as? String,
let annonce = jsonElement["annonce"] as? String,
let journalnr = jsonElement["journal"] as? String
{
location.id = id
location.oprettelsesdato = oprettelsesdato
location.overskrift = overskrift
location.address = address
location.intro = intro
location.email = email
location.tlf = tlf
location.annonce = annonce
location.journalnr = journalnr
}
locations.append(location)
}
DispatchQueue.main.async {
//print("Check home")
self.delegate.itemsDownloaded(locations)
}
}
注意:如果jsonElement
只包含字符串,您甚至可以将字典转换为[String:String]
并删除所有 as? String
强制转换。
答案 1 :(得分:2)
我建议创建一个可选的init方法,该方法接受json并尝试创建LocationModel
。
struct LocationModel {
var id: String
var oprettelsesdato: String
var overskrift: String
var address: String
var intro: String
var email: String
var tlf: String
var annonce: String
var journalnr: String
init?(json: [String:Any]) {
guard
let id = json["id"] as? String,
let oprettelsesdato = json["oprettelsesdato"] as? String,
let overskrift = json["overskrift"] as? String,
let address = json["address"] as? String,
let intro = json["intro"] as? String,
let email = json["email"] as? String,
let tlf = json["tlf"] as? String,
let annonce = json["annonce"] as? String,
let journalnr = json["journal"] as? String else { return }
self.id = id
self.oprettelsesdato = oprettelsesdato
self.overskrift = overskrift
self.address = address
self.intro = intro
self.email = email
self.tlf = tlf
self.annonce = annonce
self.journalnr = journalnr
}
}
然后,在parseJSON
函数中,您可以使用NSMutableArray
而不是[LocationModel]
。这样我们就可以使用flatMap
直接[[String:Any]]
json元素数组([LocationModel]
)到json.flatMap { LocationModel(json: $0) }
。
func parseJSON() {
var locations = [LocationModel]()
do{
if let json = try JSONSerialization.jsonObject(with: data as Data, options: []) as? [[String:Any]] {
locations = json.flatMap { LocationModel(json: $0) }
}
} catch let error as NSError {
print(error)
}
DispatchQueue.main.async {
self.delegate.itemsDownloaded(locations)
}
}
答案 2 :(得分:1)
对于您的问题至关重要的是这一部分as! NSMutableArray
:
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
即使在较旧的iOS中,将NSJSONSerialization.JSONObjectWithData
的结果转换为NSMutableArray
也不是保证操作(当您未指定{{1}时}选项)。
看到您的整个代码,您不会改变.mutableContainers
,因此您可以使用简单的jsonResult
而不是NSArray
:
NSMutableArray
我建议您使用Swift类型,例如 var jsonResult: NSArray = NSArray()
do{
jsonResult = try JSONSerialization.jsonObject(with: self.data as Data) as! NSArray
} catch let error as NSError {
print(error)
}
,Data
或Array
,而不是Dictionary
,NSData
(NSArray
)或NSMutableArray
。但这对你的情况并不重要。