【问题标题】:JSON returns null - and crashes app (check data first)JSON 返回 null - 并使应用程序崩溃(首先检查数据)
【发布时间】:2020-08-31 01:42:11
【问题描述】:

所以我想知道如何在将返回数据发送到以下命令之前检查返回数据是否包含标题。

guard let urls = URL(string: "https://api.drn1.com.au:9000/nowplaying/\(stationurl)?uuid=\(MusicPlayer.uuid!)") else { return }
              
              
              URLSession.shared.dataTask(with: urls) { ( data, _, _) in
             
            
               // Based on the updated structs, you would no
                  // longer be decoding an array
                if(data != nil){
                 
               let podcast = try! JSONDecoder().decode(Nowplayng.self, from: data!)
                   
                  DispatchQueue.main.async{
                      // The array is stored under programs now
                   
                    completion(podcast.data.first!.track)
                    
                  }
                }
              }
       .resume()
    
   }

因为根据 Crashlytics 以下内容

 let podcast = try! JSONDecoder().decode(Nowplayng.self, from: data!)

如果应用没有标题,则会导致应用崩溃

podcast.data.first!.track.title

我从 Crashlytics 得到的错误。

Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "track", intValue: nil), CodingKeys(stringValue: "title", intValue: nil)], debugDescription: "Expected String value but found null instead.", underlyingError: nil)): file /Users/russellharrower/Apps/vscroll/vscroll/Core/NowPlaying.swift, line 57

经过进一步检查,我发现上面写着stringValue: "data", intValue: nil

太好了,因为我需要做的就是在将它发送到 try 脚本之前检查一下?

【问题讨论】:

  • 错误告诉你路径data/array[0]/track/title 为nil。如果您的操作可能失败,则不应使用try!。在这种特定情况下,您要么需要修复模型以接受选项,要么修复 Web 服务以确保它永远不会为该特定路径发送 nil 数据。

标签: ios swift codable decodable


【解决方案1】:

try 的重点是如果有问题就抛出错误。通过使用try!,您保证不会出现问题,并在您错了时要求程序崩溃。出现问题,所以程序崩溃了。

由于总是有可能从服务器获取错误数据,因此您永远不应该在结果中使用try!。使用 do/catch 处理错误。

URLSession.shared.dataTask(with: urls) { ( data, _, _) in
    if let data = data {
        do {
            let podcast = try JSONDecoder().decode(Nowplayng.self, from: data)
            if let track = podcast.data.first?.track {
                DispatchQueue.main.async {
                    completion(track)
                }
            }
            // But what do you want to do if there isn't a track here? (see below)
        } catch {
            // here, you need to deal with the error. At a minimum you need to
            // log it. But you likely need to modify your completion handler to
            // accept a Result or other way of passing errors back.
        }
    }
    // And here, too. What if there's a web server error response? (see above)
}

这里没有简单的答案;这取决于你想要的行为。但一个好的开始是更改您的completion 函数以接受Result<Track, Error> 而不仅仅是轨道。这样一来,您既可以传递失败也可以传递成功。

【讨论】:

    猜你喜欢
    • 2021-05-30
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    相关资源
    最近更新 更多