Я загружаю удаленные данные JSON и хочу, чтобы мой экран загрузки оставался включенным до завершения загрузки. Как только мой метод синтаксического анализа завершит работу, должен быть вызван переход для автоматического перехода к следующему представлению.
Я убедился, что мои данные правильно загружаются и анализируются. Моя функция performSegue вызывается даже тогда, когда я устанавливаю точку останова. Но приложение все еще не переходит к следующему просмотру.
Здесь я вызываю свой метод синтаксического анализа, а затем сразу вызываю желаемый переход:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
downloadSources(atURL: "https://newsapi.org/v1/sources?language=en")
performSegue(withIdentifier: "loadingFinished", sender: self)
}
Для справки, если вам это нужно, вот мой метод синтаксического анализа полностью:
func downloadSources(atURL urlString: String) {
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
if let validURL = URL(string: urlString) {
var request = URLRequest(url: validURL)
request.setValue("49fcb8e0fa604e7aa461ee4f22124177", forHTTPHeaderField: "X-Api-Key")
request.httpMethod = "GET"
let task = session.dataTask(with: request) { (data, response, error) in
if error != nil {
assertionFailure()
return
}
guard let response = response as? HTTPURLResponse,
response.statusCode == 200,
let data = data
else {
assertionFailure()
return
}
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
guard let sources = json["sources"] as? [[String: Any]]
else {
assertionFailure()
return
}
for source in sources {
guard let id = source["id"] as? String,
let name = source["name"] as? String,
let description = source["description"] as? String
else {
assertionFailure()
return
}
self.sources.append(Source(id: id, name: name, description: description))
}
}
}
catch {
print(error.localizedDescription)
assertionFailure()
}
}
task.resume()
}
}
Заранее спасибо.
Знаете ли вы, что performSegue вызывается сразу после downloadSourcesбез в ожидании завершения загрузки из-за асинхронного поведения dataTask?





Похоже, что обратный вызов закрытия - это то, что вы хотите.
typealias CompletionHandler = ((_ success:Bool) -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
downloadSources(atURL: "www.example.com", completion: {
if success {
performSegue(withIdentifier: "loadingFinished", sender: self)
return
}
// otherwise deal with failure
})
}
func downloadSources(atURL urlString: String, completion: CompletionHandler) {
if error != nil {
completion?(false)
return
}
// finish downlaod
completion?(true)
}
if completion != nil { completion!(true) } очень объективный с-иш. В Swift есть Optional Chaining. Пишите просто completion?(true). И typealias должен быть ... = ((Bool) -> Void)?. Метка параметра вообще не используется при вызове замыкания.
Я уверен, что делаю глупые ошибки. Это решение, похоже, частично работает, поскольку я могу печатать на консоли с целевого контроллера. Однако сам вид назначения все еще отображается.
Забудь! Мне удалось заставить его работать правильно, вызвав super.viewDidLoad в закрытии. Спасибо!
@vadian верен Я обновил выполнение закрытия, чтобы использовать необязательную цепочку.
Отладка с использованием метода переопределения prepareForSegue. Проверьте контроллер назначения и свой идентификатор.