如果某些数据是NSNull

时间:2016-04-19 19:45:43

标签: ios json swift twitter

我目前正在通过Twitter的Search API提取数据。

收到数据后,我正在尝试解析并将数据保存到我的TweetDetails类(这是保存作者的名字,他们的个人资料图片的网址,推文的文字,位置的推文,推文ID和用户ID)。

在某些情况下,推文没有位置(我认为如果他们转发的话就有事可做)和某个字典(这里是tweetsDict [" place"])否则将保留该信息,而不是返回NSNull。

在这些情况下,我收到此错误

  

无法转换类型的值' NSNull' (0x1093a1600)到' NSDictionary' (0x1093a0fe8)。

这是我的代码,因为我正在尝试解析数据并将其保存到TweetDetails类中的对象

    client.sendTwitterRequest(request) { (response, data, connectionError) -> Void in
        if connectionError != nil {
            print("Error: \(connectionError)")
        }
        do {
            let json = try NSJSONSerialization.JSONObjectWithData(data!, options: [])

            if let tweets = json["statuses"] as? [NSDictionary] {
                for tweetsDict in tweets {
                    let text = tweetsDict["text"] as! String
                    let tweetID = tweetsDict["id_str"] as! String
                    let place = tweetsDict["place"] as! NSDictionary

                    // this line ^^ is where the error occurs
                    let city = place.valueForKey("full_name")
                    let user = tweetsDict["user"] as! NSDictionary
                    let userID = user.valueForKey("id_str")
                    let screenName = user.valueForKey("screen_name")!
                    let avatarImage = user.valueForKey("profile_image_url_https")!

                    let tweet = TweetDetails(authors: screenName as! String, profileImages: avatarImage as! String, tweetTexts: text, tweetLocations: city as! String , tweetIDs: tweetID , userIDs: userID as! String)
                    self.allTweets.append(tweet)
                    self.tweetTableView.reloadData()
                }
            }
        } catch let jsonError as NSError {
            print("json error: \(jsonError.localizedDescription)")
        }
    }

我试图制作一些“if-let'为这些场合提供替代方案的陈述,但没有任何效果。

当某些JSON数据作为NSNull返回时,有人可以帮我创建一个自定义替代方案。 (甚至可以简单地将我的" city"变量转换为字符串"未知位置"在数据返回NSNull的情况下)。

在此先感谢您,如果我还有其他任何内容可以添加,请与我们联系,以便更清楚地了解此问题。

2 个答案:

答案 0 :(得分:2)

正如其他人所指出的,您可以使用可选绑定(@IBAction func buttonTapped(sender: UIButton) { dispatch_async(dispatch_get_main_queue()) { let vc = self.storyboard!.instantiateViewControllerWithIdentifier(self.SendViewControllerID) as! SendViewController self.navigationController!.pushViewController(vc, animated: true) } } ),或者,在这种情况下,更简单,只需使用可选链接:

if let

这样,let city = tweetsDict["place"]?["full_name"] as? String 是可选的,即如果没有找到任何值,因为没有cityplace条目,则它将是full_name

但是,似乎您的nil强制TweetDetails加注city。它绝对需要一个城市吗?最好更改此方法,以便String是可选的,并在那里优雅地处理city值。或者,您可以将nil的{​​{1}}值替换为其他字符串,例如使用nil合并运算符:

city

如果找到,则返回城市,"未知城市"如果没有。

答案 1 :(得分:0)

我在你的代码中看到很多强制数据类型转换是非常危险的,特别是在解析JSON时。处理可空性的正确方法不是通过尝试我们在objective-c中做同样的事情来避免它,而是准备接收nil并做出相应的反应。您的数据模型应该表示某个推文有时没有位置的事实,因此TweetDetails的某些属性应该标记为可选项。

下面的代码示例完全没有经过测试,但是让您了解代码处理可空性的样子。

client.sendTwitterRequest(request) { (response, data, connectionError) -> Void in
    if connectionError != nil {
        print("Error: \(connectionError)")
    }
    do {
        let json = try NSJSONSerialization.JSONObjectWithData(data!, options: [])
    if let tweets = json["statuses"] as? [[String: AnyObject]] {
        for tweetsDict in tweets {
            if let text = tweetsDict["text"] as? String,
            tweetID = tweetsDict["id_str"] as? String {

                var city: String?
                if let place = tweetsDict["place"] as? [String: AnyObject] {
                    city = place.valueForKey("full_name")
                }

                var userID: String?
                var screenName: String?
                var avatarImage: String?
                if let user = tweetsDict["user"] as? [String: AnyObject] {
                    userID = user["id_str"] as? String
                    screenName = user["screen_name"] as? String
                    avatarImage = user["profile_image_url_https"] as? String
                }

                let tweet = TweetDetails(authors: screenName, profileImages: avatarImage, tweetTexts: text, tweetLocations: city, tweetIDs: tweetID, userIDs: userID)
                self.allTweets.append(tweet)
            }
        }
        self.tweetTableView.reloadData()
    }
} catch let jsonError as NSError {
    print("json error: \(jsonError.localizedDescription)")
    }
}