2016-10-21 5 views
14

Я очень новичок в Swift.Преобразование данных в строку в Swift 3

Я хочу создать что-то вроде API на Swift для моего образовательного приложения.

У меня есть этот код:

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)) все будет в порядке, и я могу видеть data в XCode консоли.

Итак, как я могу преобразовать данные в строку?

+0

Основная проблема заключается в том, что вы не можете вернуть что-то из асинхронной функции. Вам нужен обработчик завершения. – vadian

+0

@vadian. Можете ли вы преобразовать мой код в обработчик завершения кода? Я много читал о них, и я не понимаю, что мне нужно разделить в моем коде. – IlyaGutnikov

+0

Я написал ответ. – vadian

ответ

21

Это пример использования обработчика завершения:

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. Скорее всего, веб-служба вернет JSON, поэтому вам может потребоваться десериализация JSON в массив или словарь.


В более сложном варианте создать перечисление с двумя случаями и соответствующими значениями

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() 
} 

На стороне вызывающего абонента A switch заявление отделяет случаи.

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

Большое спасибо! – IlyaGutnikov

+0

Извините, но я не понимаю, как я могу получить возвращаемое значение из getFilm? Я имею в виду что-то вроде этого 'var test = getFilm()' – IlyaGutnikov

+0

Your 'MyClass.getFilm (filmID: 12345) {result in print (result) }' просто взорвать мой разум. Я думаю, что было бы просто - у меня есть функция с входными и выходными параметрами, и я понимаю, как я могу получить «результат» во внешнем коде. – IlyaGutnikov

Смежные вопросы