显示来自 URL 的图像,Swift 4.2

Ger*_*acs 1 json nsdictionary ios swift

我是一个相当不错的 Objective C 开发人员,我现在正在学习 Swift(我发现其中非常困难,不仅因为新概念,例如可选,还因为 Swift 不断发展,而且许多可用的教程都是严重过时)。

目前,我正在尝试将 JSON 从 url 解析为 NSDictionary,然后使用其值之一来显示图像(这也是一个 url)。像这样的东西:


URL -> NSDictionary -> 从 url 初始化 UIImage -> 在 UIImageView 中显示 UIImage


这在 Objective C 中很容易(甚至可能有更短的答案):

NSURL *url = [NSURL URLWithString:@"https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"];
NSData *apodData = [NSData dataWithContentsOfURL:url];
NSDictionary *apodDict = [NSJSONSerialization JSONObjectWithData:apodData options:0 error:nil];
Run Code Online (Sandbox Code Playgroud)

上面的代码片段给了我一个标准的 NSDictionary,我可以在其中引用“url”键来获取我想要显示的图像的地址:


“网址”:“ https://apod.nasa.gov/apod/image/1811/hillpan_apollo15_4000.jpg


然后我将其转换为 UIImage 并将其提供给 UIImageView:

NSURL *imageURL = [NSURL URLWithString: [apodDict objectForKey:@"url"]];
NSData *imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage *apodImage = [UIImage imageWithData:imageData];

UIImageView *apodView = [[UIImageView alloc] initWithImage: apodImage];
Run Code Online (Sandbox Code Playgroud)

现在,我基本上是在尝试在 Swift 中复制上述 Objective C 代码,但不断遇到障碍。我尝试了几个教程(其中一个实际上做了完全相同的事情:显示 NASA 图像),并找到了一些堆栈溢出的答案,但没有一个可以提供帮助,因为它们要么已经过时,要么它们的处理方式与我需要的不同。

所以,我想请社区提供 Swift 4 代码来解决这些问题:

1. Convert data from url into a Dictionary
2. Use key:value pair from dict to get url to display an image
Run Code Online (Sandbox Code Playgroud)

如果还不是太多,我还想在代码旁边要求详细说明,因为我希望答案是此任务的一个综合“教程”,我认为目前在任何地方都没有。

谢谢!

vad*_*ian 5

首先我很确定在半年内你会发现Objective-C非常复杂和困难。

其次,甚至不鼓励您的 ObjC 代码。不要使用同步Data(contentsOf方法从远程 URL 加载数据。无论使用哪种语言都使用异步方式,例如(NS)URLSession.

不要用粉底集合类型NSArrayNSDictionary斯威夫特。NS...如果有本地 Swift 对应物,基本上根本不要使用类。

在 Swift 4 中,您可以轻松地将带有Decodable协议的 JSON直接解码为(Swift)结构,
甚至可以将 URL 字符串解码为URL.

创建一个结构

struct Item: Decodable {
    // let copyright, date, explanation: String
    // let hdurl: String
    // let mediaType, serviceVersion, title: String
    let url: URL
}
Run Code Online (Sandbox Code Playgroud)

如果您需要的不仅仅是 URL,请取消注释这些行。

并用两个数据任务加载数据。

let url = URL(string: "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY")! 

let task = URLSession.shared.dataTask(with: url) { (data, _, error) in
    if let error = error { print(error); return }
    do {
       let decoder = JSONDecoder()
       // this line is only needed if all JSON keys are decoded
       decoder.keyDecodingStrategy = .convertFromSnakeCase
       let result = try decoder.decode(Item.self, from: data!)
       let imageTask = URLSession.shared.dataTask(with: result.url) { (imageData, _, imageError) in
           if let imageError = imageError { print(imageError); return }
           DispatchQueue.main.async {
               let apodImage = UIImage(data: imageData!)
               let apodView = UIImageView(image: apodImage)
               // do something with the image view
           }
       }
       imageTask.resume()
   } catch { print(error) }
}
task.resume()
Run Code Online (Sandbox Code Playgroud)