尝试将 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 latvar 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”的主要内容,如果未能解决你的问题,请参考以下文章

从 JSON 响应创建字符串数组 Alamofire

尝试反序列化 JSON 对象数组,其中对象具有数组作为属性。我可以将数组元素映射到类的特定属性吗?

Alamofire 响应对象映射

将firebase响应映射到类

将 alamofire json 响应转换为变量

将 alamofire 响应解析为 JSON 返回 nil