尝试将 AlamoFire JSON 响应映射到类并接收“致命错误:在展开可选时意外发现 nil”
Posted
技术标签:
【中文标题】尝试将 AlamoFire JSON 响应映射到类并接收“致命错误:在展开可选时意外发现 nil”【英文标题】:Trying to map an AlamoFire JSON response to a Class and receiving "Fatal Error: Unexpectedly found nil while unwrapping optional" 【发布时间】:2015-07-07 04:47:19 【问题描述】:我正在使用 AlamoFire 拉取我的 API 来填充我的 tableView 的单元格。该应用程序能够构建,但很快就会崩溃,并出现习惯性的“致命错误:在展开可选值时意外发现 nil”。我已经检查了所有可选值,但无法确定是哪一个导致了问题。 Xcode 说问题出现在 AlamoFire 的 .map 部分。任何帮助将不胜感激。
在我开始编写代码之前,我的 JSON 中的一个值对于每个键都是空的(我没有编写 JSON)。它不是“空”,只是空。即使我没有将该键映射到我的类,这是否会导致问题?
JSON 是一个字典数组。发出 .GET 请求后,我将获取 JSON 响应并将其映射到我初始化为类类型数组的变量。
代码如下:
var users = [User]() //User is the class I created
var results = NSMutableOrderedSet()
let url = "http://www.example.com"
let appToken = "abcd12345"
Alamofire.request(.GET, url, parameters: ["appToken": appToken]).responseJSON()
(_, _, JSON, _) in
let users = (JSON!.valueForKey("results") as! [NSDictionary]).map
User(name: $0["username"] as! String, image: $0["profileImage"] as! String, email: $0["email"] as! String, lat: $0[("lat" as NSString).doubleValue] as! Double, lon: $0[("lon" as NSString).doubleValue] as! Double, distance: $0["status"] as! Int)
self.results.addObjectsFromArray(users)
self.localTableView!.reloadData()
这是我的 User.swift 中的 Class 类型:
class User: NSObject, MKAnnotation
var name:String!
var profileImage:String!
var email:String!
var lat:Double
var lon:Double
var distance:Int!
var coordinate: CLLocationCoordinate2D
var title: String
var subtitle: String
var imageName: String
var userID:String!
var firstName: String!
var lastName: String!
init(name:String, image:String, email:String, lat:Double, lon:Double, distance:Int)
self.name = name
self.profileImage = image
self.email = email
self.lat = lat
self.lon = lon
self.distance = distance
self.coordinate = CLLocationCoordinate2DMake(lat, lon)
self.title = name
self.subtitle = twitterName
self.imageName = "image.png"
我已经阅读了一些帮助部分,我可能没有正确初始化我的类的实例,但我尝试了所有组合都无济于事。我也尝试过使用 NSMutableDictionary,但这并没有解决任何问题。
【问题讨论】:
可能是username
/profileImage
/email
/...
之一为nil
你为什么不为用户创建一个初始化器,它将字典作为初始化器,这将使你的代码更清晰,更容易使用
我至少在 Swift 1.2 中的经验是,工厂函数仍然比可失败的初始化程序更容易使用。如果不填充所有 let 字段,您将无法从失败的初始化程序返回,最后我还是尝试了。在使用字典进行初始化时,您肯定需要处理缺少键或类型错误的值的情况。只需在初始化程序的签名中使用换行符,它就会相当可读。
感谢大家的帮助。我发现我的零。我将在下面发布详细信息。
使用以下链接,它解决了我的问题。 Link
【参考方案1】:
感谢大家的回复。他们都非常乐于助人。
当我在上面分享代码时,我将部分代码缩短为基本要素,但在将 var lat
和 var lon
映射到我的用户数组时发现了问题。在 API 中,它们是双精度的,但被放在引号中,因此将其作为字符串读取。我意识到了这个问题并编写了代码将它们从字符串转换为双精度。但是,我把它放在了我的代码的.map
部分(上面没有看到)。那里可能有一种方法可以做到这一点,但它从未对我有用。
相反,我通过更改我的class User
以进行如下更改来找到我的解决方案:
let lat: String
let lon: String
var latDouble: Double
var lonDouble: Double
然后初始化如下:
self.latDouble = (lat as NSString).doubleValue
self.lonDouble = (lon as NSString).doubleValue
我还结合了 SwiftyJSON 来检索我的 API 数据,然后按如下方式填充我的数组:
Alamofire.request(.GET, url, parameters: ["appToken": appToken]).responseJSON()
(_,_,json,_) in
if (json != nil)
var jsonObj = JSON(json!)
if let userArray = jsonObj ["results"].array
for userDict in userArray
var name: String! = userDict["username"].string
var email: String! = userDict["email"].string
var image: String! = userDict["profileImage"].string
var lat: String! = userDict["lat"].string
var lon: String! = userDict["lon"].string
var distance: Int! = userDict["status"].int
var user = User(name: name, image: image, email: email, lat: lat, lon: lon, distance: distance)
self.users.append(user)
self.localTableView.reloadData()
我意识到这可能不是最好的或唯一的解决方案,但它解决了我的问题。我希望这对其他人有帮助。再次感谢。
【讨论】:
【参考方案2】:在你的回调中有很多可选的解包,其中任何一个都可能是 nil。您需要进入调试器并检查返回的 JSON。如果您在使用调试器时遇到困难,可以在尝试使用 JSON 变量并查看其内容之前打印()它。
提示:不要在类属性上使用隐式展开的可选类型。这不是一种安全的做法。如果您在创建类实例后不打算修改属性,请使用 let name: String 例如而不是 var name: String!。让编译器帮你写出正确的程序。
【讨论】:
感谢您的帮助。我是编程新手,并认为我已经彻底查看了调试器,但在您发表评论后,我更深入地查看并发现我缺少的 nil 。我将在下面发布更详细的帐户。以上是关于尝试将 AlamoFire JSON 响应映射到类并接收“致命错误:在展开可选时意外发现 nil”的主要内容,如果未能解决你的问题,请参考以下文章