Swift数组在离开函数后返回空



当运行下面的代码时,返回coordsArraygetCrimes函数外部时不返回值,但在内部时打印值。我在网上读到关于使用信号量的文章,但没有这方面的经验,所以希望有人能指导我如何正确返回coordsArray

func getCrimes(completion: @escaping ([Crime])->()){
//guard let crimeURL = URL(string: "https://data.police.uk/api/crimes-street/drugs?poly=51.5623,-2.5709:51.4952,-2.7292:51.4008,-2.6235:51.4028,-2.4875:51.4569,-2.4274&date=(currentYear)-(currentMonth)") else {return}
guard let crimeURL = URL(string: "https://data.police.uk/api/crimes-street/drugs?poly=51.5623,-2.5709:51.4952,-2.7292:51.4008,-2.6235:51.4028,-2.4875:51.4569,-2.4274&date=2022-02") else {return}

URLSession.shared.dataTask(with: crimeURL) { (data, _, _) in
let crimes = try! JSONDecoder().decode([Crime].self, from: data!)
DispatchQueue.main.async{
completion(crimes)
}
}
.resume()
}
func getLocations() -> [Coords] {
var coordsArray : [Coords] = []
getCrimes{ (crimes) in
self.crimes = crimes
for crime in crimes{
let lat = Double(crime.location.latitude)!
let long = Double(crime.location.longitude)!
coordsArray.append(Coords(latitude:lat, longitude: long))
}
print(coordsArray) //Does display the array
}
print(coordsArray)//Doesn't display the array
return coordsArray //Blank Array
}

在主线程中执行异步函数。主线程不会等待那个异步线程,它会继续执行函数中的下一个命令。

func getLocations() -> [Coords] {
// Main Thread
var coordsArray : [Coords] = []

getCrimes { (crimes) in
// Async Thread, suppose 100ms to complete
self.crimes = crimes
for crime in crimes{
let lat = Double(crime.location.latitude)!
let long = Double(crime.location.longitude)!
coordsArray.append(Coords(latitude:lat, longitude: long))
}
print(coordsArray)
}


// Main thread, very fast, execute immediately after execute `getCrimes`, 
// => coordsArray = [] because Async Task not complete
print(coordsArray)
return coordsArray
}

您可以在主线程等待,但不应该使用它,因为它锁定了主线程,UI将停止

func getCrimes(completion: @escaping ([Crime])->()){
//guard let crimeURL = URL(string: "https://data.police.uk/api/crimes-street/drugs?poly=51.5623,-2.5709:51.4952,-2.7292:51.4008,-2.6235:51.4028,-2.4875:51.4569,-2.4274&date=(currentYear)-(currentMonth)") else {return}
guard let crimeURL = URL(string: "https://data.police.uk/api/crimes-street/drugs?poly=51.5623,-2.5709:51.4952,-2.7292:51.4008,-2.6235:51.4028,-2.4875:51.4569,-2.4274&date=2022-02") else {return}

URLSession.shared.dataTask(with: crimeURL) { (data, _, _) in
let crimes = try! JSONDecoder().decode([Crime].self, from: data!)

// The main thread was lock, so need execute completion at other thread
DispatchQueue.global(qos: .default).async{
completion(crimes)
}
}
.resume()
}
func getLocations() -> [Coords] {
var coordsArray : [Coords] = []
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()

getCrimes{ (crimes) in
self.crimes = crimes
for crime in crimes{
let lat = Double(crime.location.latitude)!
let long = Double(crime.location.longitude)!
coordsArray.append(Coords(latitude:lat, longitude: long))
}
print(coordsArray) //Does display the array
dispatchGroup.leave()
}
dispatchGroup.wait() // Lock thread until complete async task
print(coordsArray)//Doesn't display the array
return coordsArray //Blank Array
}

相反,您可以使用转义闭包

func getLocations(completeGetLocation: (([Coords]) -> Void)?) {
var coordsArray : [Coords] = []
getCrimes { (crimes) in
self.crimes = crimes
for crime in crimes{
let lat = Double(crime.location.latitude)!
let long = Double(crime.location.longitude)!
coordsArray.append(Coords(latitude:lat, longitude: long))
}
print(coordsArray) //Does display the array
completeGetLocation?(coordsArray)
}
}

最新更新