web-dev-qa-db-ja.com

Swift 3でデータを文字列に変換

私はSwiftが初めてです。

Swift教育アプリ用にAPIのようなものを作成したい。

私はこのコードを持っています:

_    static func getFilm(filmID: Int) -> String {

    print("getFilm")

    let url = URL(string: "https://api.kinopoisk.cf/getFilm?filmID=\(filmID)")!
    var request = URLRequest(url: url)

    var returnData: String = ""

    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        if var responseVar = response, var dataVar = data {
            print(responseVar)
            returnData = String(data: dataVar, encoding: .utf8)
        } else {
            print(error)
        }
    }

    task.resume()

    return returnData
}
_

そして、次の行でデータを文字列に変換しようとしています:returnData = String(data: dataVar, encoding: .utf8)

Swiftコンパイラーはエラーを出し、この行をreturnData = String(data: dataVar, encoding: .utf8)!に変更します。この行を実行すると、空のreturnData変数が取得されます。

基本的なサンプル行print(String(data: data, encoding: .utf8))を使用すると、すべてが正常になり、XCodeコンソールにdataが表示されます。

だから、どのようにデータを文字列に変換できますか?

23
IlyaGutnikov

これは、完了ハンドラーを使用した例です。

class func getFilm(filmID: Int, completion: @escaping (String) -> ()) {
    let url = URL(string: "https://api.kinopoisk.cf/getFilm?filmID=\(filmID)")!

    URLSession.shared.dataTask(with:url) { (data, response, error) in
      if error != nil {
        print(error!)
        completion("")
      } else {
        if let returnData = String(data: data!, encoding: .utf8) {
          completion(returnData)
        } else {
          completion("")
        }
      }
    }.resume()
}

そして、あなたはそれを呼ぶ

MyClass.getFilm(filmID:12345) { result in
   print(result)
}

エラーの場合、完了ハンドラーは空の文字列を返します。

MyClassは、getFilmメソッドを囲むクラスです。ほとんどの場合、WebサービスはJSONを返すため、JSONを配列または辞書にデシリアライズする必要がある場合があります。


より洗練されたバージョンでは、2つのケースと関連する値を持つ列挙型を作成します

enum ConnectionResult {
  case success(String), failure(Error)
}

Swiftの微妙な力を実証するためのもう少しの努力で、単一オブジェクトでエラーの成功時にエラー文字列を返すことができます。

class func getFilm(filmID: Int, completion: @escaping (ConnectionResult) -> ()) {
    let url = URL(string: "https://api.kinopoisk.cf/getFilm?filmID=\(filmID)")!

    URLSession.shared.dataTask(with:url) { (data, response, error) in
      if error != nil {
        completion(.failure(error!))
      } else {
        if let returnData = String(data: data!, encoding: .utf8) {
          completion(.success(returnData))
        } else {
          completion(.failure(NSError(domain: "myDomain", code: 9999, userInfo: [NSLocalizedDescriptionKey : "The data is not converible to 'String'"])))
        }
      }
    }.resume()
}

呼び出し側では、switchステートメントがケースを分離します。

MyClass.getFilm(filmID:12345) { result in
    switch result {
    case .success(let string) : print(string)
    case .failure(let error) : print(error)
    }
}
36
vadian