iOS开发

iOS网络请求(Networking)及处理 Json

2021-06-22  本文已影响0人  _浅墨_

我们知道,空格不是 URL 中的有效字符, 除此,还有许多其它特殊字符也不是,例如 < 或 > 符号。因此对特殊字符必须进行转义,即 URL 编码。

例如,我们可以将空格编码为 + 号或字符序列 %20。

幸运的是,String 类现在已经可以进行这种编码了。 因此,我们只需添加一些代码就可以完成 URL 转码:

func iTunesURL(searchText: String) -> URL {
  let encodedText = searchText.addingPercentEncoding(
      withAllowedCharacters: CharacterSet.urlQueryAllowed)!  // Add this
  let urlString = String(
    format: "https://itunes.apple.com/search?term=%@", 
    encodedText)                                             // Change this
  let url = URL(string: urlString)
  return url!
}

以上代码调用 addingPercentEncoding(withAllowedCharacters:) 方法,创建一个新字符串,其中的所有的特殊字符被转码。我们使用这个新字符串进行网络请求。

URL: 'https://itunes.apple.com/search?term=pokemon%20go'

空格被转码为 %20。% 表示转义字符,20 是空格的 UTF-8 值。这里我们还可以尝试转码带有其它特殊字符(例如 # 和 * 甚至 Emoji)的 url,看看会发生什么。

解析 JSON 准备工作

从 Swift 4 开始,Codable 可以解析 JSON 了。

还记得如何使用 PropertyListDecoder 解码支持 Codable 协议的 plist 数据,以读取和保存清单中的数据吗? 好吧,属性列表并不是 Codable 支持的唯一开箱即用格式——它也支持 JSON!

为了让我们的 app 能够将 JSON 数据直接读入相关数据结构,我们需要将它设置为遵守 Codable 协议。

比如 SearchResult.swift:

class ResultArray: Codable {
    var resultCount = 0
    var results = [SearchResult]()
}

class SearchResult: Codable {
  var artistName: String? = ""
  var trackName: String? = ""
  
  var name: String {
    return trackName ?? ""
  }
}

解析 JSON

SearchViewController.swift:

func performStoreRequest(with url: URL) -> Data? {  // Change to Data?
 do {
   return try Data(contentsOf:url)                 // Change this line
 } catch {
   . . .
 }
}

func parse(data: Data) -> [SearchResult] {
  do {
    let decoder = JSONDecoder()
    let result = try decoder.decode(
      ResultArray.self, from: data)
    return result.results
  } catch {
    print("JSON Error: \(error)")
    return []
  }
}

我们使用 JSONDecoder 对象将来自服务器的响应数据转换为临时 ResultArray 对象,我们可以从中提取 results 属性。

处理 Json,优化如下:

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
  if !searchBar.text!.isEmpty {
    . . .
    print("URL: '\(url)'")
    if let data = performStoreRequest(with: url) {  // Modified
      let results = parse(data: data)               // New line
      print("Got results: \(results)")              // New line
    }
    tableView.reloadData()
  }
}

以上打印出的只是对象,没有显示对象内容。接下来我们继续优化,打印更多详细信息。

打印对象内容信息

修改 SearchResult.swift,令其遵守 CustomStringConvertible 协议:

class SearchResult: Codable, CustomStringConvertible {

CustomStringConvertible 协议允许对象具有自定义字符串表示形式。即,该协议允许对象具有描述对象及其属性的自定义字符串。

修改 SearchResult 类:

var description: String {
  return "\nResult - Name: \(name), Artist Name: \(artistName ?? "None")"
}

注意上面代码中 ?? 运算符,它被称为空合( nil-coalescing)运算符。意思是,如果变量有值,则返回该变量,如果没有,则返回 ?? 运算符右侧的值作为默认值。

比如:

let username = loginName ?? "Guest"

loginName 表示为可选性,如果loginName 为空,则使用默认名称 Guest

再次打印,详细信息出来了:

URL: 'https://itunes.apple.com/search?term=Metallica'
Got results: [
Result - Name: Enter Sandman, Artist Name: Metallica, 
Result - Name: Nothing Else Matters, Artist Name: Metallica, 
Result - Name: The Unforgiven, Artist Name: Metallica, 
. . .

上一篇下一篇

猜你喜欢

热点阅读