如何使用 swift 中异步函数的数据退出 for 循环?
How to exit a for loop with data from an async function in swift?
函数findMediaLimit return 最高的i,从cURL接收到?
class func findMediaLimit(IgBusinessAccount: String, token: String) {
let igBId = IgBusinessAccount
for i in 1...12 {
guard let encodedUrl = self.buildURLAPIGraph(IgBusinessAccount: igBId, token: token, i: i) else { return }
//Async function that returns different i's in random order
self.cURL(urlT: encodedUrl) { (result) in
print(i)
//return the highest i
}
}
}
我创建此功能是为了过滤转换为企业 Instagram 帐户后发布的媒体。
这是我的 cURL 函数
class func cURL (urlT: String,Completion block: @escaping ((OfficialProfile) -> ())) {
//visuJson (urlT: urlT)
GetJson.loadJson(fromURLString: urlT) { (result) in
switch result {
case .success(let data):
//Parse
do {
let decodedData = try JSONDecoder().decode(OfficialProfile.self, from: data)
if decodedData.username != nil {
block(decodedData)
}
} catch {
print("decode error: ",error)
}
case .failure(let error):
print("loadJson error:", error)
}
}
}
那是我的 loadJson 函数
class func loadJson(fromURLString urlString: String,
completion: @escaping (Result<Data, Error>) -> Void) {
if let url = URL(string: urlString) {
let urlSession = URLSession(configuration: .default).dataTask(with: url) { (data, response, error) in
if let error = error {
completion(.failure(error))
}
if let data = data {
completion(.success(data))
}
}
urlSession.resume()
}
}
要了解您显然正在尝试执行的操作存在什么问题,让我们以更简单的方式进行模拟。我将使用异步随机数生成器。在操场上试试这个:
func delay(_ delay:Double, closure:@escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
func asyncRand(_ completion: @escaping (Int) -> ()) {
let d = Double.random(in: 1...3)
delay(d) {
let i = Int.random(in: 1...100)
completion(i)
}
}
func go() {
for i in 1...12 {
asyncRand() { result in
print(i, result)
}
}
print("finished")
}
go()
典型 运行 的结果可能是:
finished
8 13
1 15
9 9
10 56
7 57
3 87
2 70
11 88
6 82
12 16
4 81
5 46
所以这里有两个问题,因为中央 asyncRand
调用的异步性质:随着时间的推移,结果无序地返回,以及 go
方法本身(循环) 在 any 结果返回之前完成,因此没有机会找出哪个结果是最大值。
为了解决这个问题,在我们等待 async/await
出现在 Swift 期间(可能最快下周),您可以使用调度组。忽略任何线程问题,我们可以这样做:
func go() {
let group = DispatchGroup()
var pairs = [[Int]]()
for i in 1...12 {
group.enter()
asyncRand() { result in
print(i, result)
pairs.append([i,result])
group.leave()
}
}
group.notify(queue: DispatchQueue.main) {
print("finished")
if let maximum = pairs.max(by: {[=12=][1] < [1]}) {
print(maximum)
}
}
}
现在的结果是(例如):
11 52
8 6
2 1
4 6
12 77
1 88
7 45
9 36
6 25
3 22
10 78
5 33
finished
[1, 88]
所以你看我们已经“等待”直到所有结果都返回,并且我们已经挑选出返回最大值的对。
所以你可以按照这些思路做一些事情。但这是否是个好主意是另一个问题。
函数findMediaLimit return 最高的i,从cURL接收到?
class func findMediaLimit(IgBusinessAccount: String, token: String) {
let igBId = IgBusinessAccount
for i in 1...12 {
guard let encodedUrl = self.buildURLAPIGraph(IgBusinessAccount: igBId, token: token, i: i) else { return }
//Async function that returns different i's in random order
self.cURL(urlT: encodedUrl) { (result) in
print(i)
//return the highest i
}
}
}
我创建此功能是为了过滤转换为企业 Instagram 帐户后发布的媒体。
这是我的 cURL 函数
class func cURL (urlT: String,Completion block: @escaping ((OfficialProfile) -> ())) {
//visuJson (urlT: urlT)
GetJson.loadJson(fromURLString: urlT) { (result) in
switch result {
case .success(let data):
//Parse
do {
let decodedData = try JSONDecoder().decode(OfficialProfile.self, from: data)
if decodedData.username != nil {
block(decodedData)
}
} catch {
print("decode error: ",error)
}
case .failure(let error):
print("loadJson error:", error)
}
}
}
那是我的 loadJson 函数
class func loadJson(fromURLString urlString: String,
completion: @escaping (Result<Data, Error>) -> Void) {
if let url = URL(string: urlString) {
let urlSession = URLSession(configuration: .default).dataTask(with: url) { (data, response, error) in
if let error = error {
completion(.failure(error))
}
if let data = data {
completion(.success(data))
}
}
urlSession.resume()
}
}
要了解您显然正在尝试执行的操作存在什么问题,让我们以更简单的方式进行模拟。我将使用异步随机数生成器。在操场上试试这个:
func delay(_ delay:Double, closure:@escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
func asyncRand(_ completion: @escaping (Int) -> ()) {
let d = Double.random(in: 1...3)
delay(d) {
let i = Int.random(in: 1...100)
completion(i)
}
}
func go() {
for i in 1...12 {
asyncRand() { result in
print(i, result)
}
}
print("finished")
}
go()
典型 运行 的结果可能是:
finished
8 13
1 15
9 9
10 56
7 57
3 87
2 70
11 88
6 82
12 16
4 81
5 46
所以这里有两个问题,因为中央 asyncRand
调用的异步性质:随着时间的推移,结果无序地返回,以及 go
方法本身(循环) 在 any 结果返回之前完成,因此没有机会找出哪个结果是最大值。
为了解决这个问题,在我们等待 async/await
出现在 Swift 期间(可能最快下周),您可以使用调度组。忽略任何线程问题,我们可以这样做:
func go() {
let group = DispatchGroup()
var pairs = [[Int]]()
for i in 1...12 {
group.enter()
asyncRand() { result in
print(i, result)
pairs.append([i,result])
group.leave()
}
}
group.notify(queue: DispatchQueue.main) {
print("finished")
if let maximum = pairs.max(by: {[=12=][1] < [1]}) {
print(maximum)
}
}
}
现在的结果是(例如):
11 52
8 6
2 1
4 6
12 77
1 88
7 45
9 36
6 25
3 22
10 78
5 33
finished
[1, 88]
所以你看我们已经“等待”直到所有结果都返回,并且我们已经挑选出返回最大值的对。
所以你可以按照这些思路做一些事情。但这是否是个好主意是另一个问题。