У меня есть функция, которая очищает файл JSON, встроенный в веб-сайт, и возвращает массив строк. Поскольку данные, которые он возвращает, очень важны для моего контроллера представления, мне нужно запустить эту функцию до загрузки представления. Он вызывается при инициализации контроллера представления.
func scrapeBuses() -> [String] {
let config = URLSessionConfiguration.default
//config.waitsForConnectivity = true
let defaultSession = URLSession(configuration: config)
let url = URL(string: link to a JSON file)
let request = NSMutableURLRequest(url: url!)
request.cachePolicy = .reloadIgnoringLocalCacheData
var loops = [String]()
let group = DispatchGroup()
group.enter()
DispatchQueue.main.async {
let task = defaultSession.dataTask(with: request as URLRequest) { data, response, error in
do {
print("Getting information from website")
if let error = error {
print(error.localizedDescription)
} else if let data = data, let response = response as? HTTPURLResponse, response.statusCode == 200 {
print("in async")
loops.append("test2")
}
}
catch { print(error)}
}
}
task.resume()
print("about to return")
//return loops
}
group.wait()
return loops
}
Поскольку он асинхронный, я добавил операторы DispatchGroup
и wait()
, чтобы мой основной поток ждал, пока эти важные данные не будут очищены, прежде чем продолжить работу с остальным потоком. Однако я заметил, что когда происходит переход к этому контроллеру вида (то есть, когда контроллер вида инициализируется), ничего больше не печатается, и моделирование останавливается. Ясно, что это означает, что основной поток ожидает завершения scrape()
, но почему он работает бесконечно? Когда я захожу на сайт, как в своем веб-браузере, так и в Rested, я вижу, что на нем правильно размещается JSON.
Edit:
Я попробовал другую версию той же функции, используя обработчик завершения вместо DispatchQueue.wait()
. Ниже приведен код:
func scrapeBuses(completion: @escaping ([String]) -> Void) {
let config = URLSessionConfiguration.default
let defaultSession = URLSession(configuration: config)
let url = URL(string: "https://www.cmunc.net/assets/appData.json")
let request = NSMutableURLRequest(url: url!)
request.cachePolicy = .reloadIgnoringLocalCacheData
var loops = [String]()
let task = defaultSession.dataTask(with: request as URLRequest) { data, response, error in
print("Getting information from website")
if let error = error {
print(error.localizedDescription)
} else if let data = data, let response = response as? HTTPURLResponse, response.statusCode == 200 {
print("in async")
loops.append("test2")
}
completion(loops)
}
task.resume()
}
А вот функция, которая вызывается контроллером вида init
:
func refresh() {
var newArray = [String]()
scrapeBuses { loops in
newArray = loops
print("calling scrapeBuses closure")
}
print(newArray)
}
Используя обработчик завершения, код выполняется правильно. Как операторы print в scrapeBuses
, так и операторы печати closeure. Огромное спасибо всем, кто предложил свое понимание.