需要为这个while循环使用异步函数吗?

huangapple go评论81阅读模式
英文:

Would I need to have an asynchronous function for this while loop?

问题

I'm fairly new to swift and programming as a whole, I have some code that will loop through a hardcoded amount which represents posts (this will always stay the same and so I hardcoded it) and run a function with the position of the where currently the while loop has got to which returns a string of an URL of a cached video file downloaded from firebase. Whenever the URL of the 10 posts is returned it gets appended into an array, which, by the end should have be full of 10 strings that are all unique urls to different videos stored on the device:

var fileArray = [String]()

func getPosts(){
    var pos = 0
    let numOfPosts = 10
    while pos <= numOfPosts{
        FeaturedPostsManager.shared.getFeaturedPosts(index: pos, completion: { url in
            if url != nil{
                self.fileArray.append(url!)
            }else{
                print("error")
            }
        })
        pos += 1
    }
    performSegue(withIdentifier: "showHome", sender: nil)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let recveiverVC = segue.destination as! HomeViewController
    recveiverVC.fileArray = fileArray
}

My problem is it seems as if the performSegue(withIdentifier: "showHome", sender: nil) gets executed before the array has even one url value in it as I can see in the console that the URLs are being retrieved successfully, just that when, in my HomeViewController, my array returns empty. Would I need some sort of asynchronous function here to only allow the performSegue(withIdentifier: "showHome", sender: nil) code execute when the while loop has finished and hence have a full array of urls?

Thanks,

Nathan

英文:

I'm fairly new to swift and programming as a whole, I have some code that will loop through a hardcoded amount which represents posts (this will always stay the same and so I hardcoded it) and run a function with the position of the where currently the while loop has got to which returns a string of an URL of a cached video file downloaded from firebase. Whenever the URL of the 10 posts is returned it gets appended into an array, which, by the end should have be full of 10 strings that are all unique urls to different videos stored on the device:

 var fileArray = [String]()

 func getPosts(){
    var pos = 0
    let numOfPosts = 10
    while pos &lt;= numOfPosts{
        FeaturedPostsManager.shared.getFeaturedPosts(index: pos, completion: { url in
            if url != nil{
                self.fileArray.append(url!)
            }else{
                print(&quot;error&quot;)
            }
        })
        pos += 1
    }
    performSegue(withIdentifier: &quot;showHome&quot;, sender: nil)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let recveiverVC = segue.destination as! HomeViewController
    recveiverVC.fileArray = fileArray
}

My problem is it seems as if the performSegue(withIdentifier: &quot;showHome&quot;, sender: nil) gets executed before the array has even one url value in it as I can see in the console that the URLs are being retrieved successfully, just that when, in my HomeViewController, my array returns empty. Would I need some sort of asynchronous function here to only allow the performSegue(withIdentifier: &quot;showHome&quot;, sender: nil) code execute when the while loop has finished and hence have a full array of urls?

Thanks,

Nathan

答案1

得分: 0

你需要一个DispatchGroup,用于在运行一系列异步调用后通知你。

func getPosts() {
    var pos = 0
    let numOfPosts = 10
    let g = DispatchGroup()  // 1
    while pos <= numOfPosts {
        g.enter()    // 2
        FeaturedPostsManager.shared.getFeaturedPosts(index: pos, completion: { url in
            if url != nil {
                self.fileArray.append(url!)
            } else {
                print("error")
            }
            g.leave()     // 3
        })
        pos += 1
    }

    g.notify(queue: .main) {      // 4
        self.performSegue(withIdentifier: "showHome", sender: nil)
    } 
}
英文:

You need a DispatchGroup which is used when you need to be notified after running a bunch of asynchronous calls

 func getPosts(){
    var pos = 0
    let numOfPosts = 10
    let g = DispatchGroup()  //// 1
    while pos &lt;= numOfPosts{
        g.enter()    //// 2
        FeaturedPostsManager.shared.getFeaturedPosts(index: pos, completion: { url in
            if url != nil{
                self.fileArray.append(url!)
            }else{
                print(&quot;error&quot;)
            }
            g.leave()     //// 3
        })
        pos += 1
    }

   g.notify(queue:.main) {      //// 4
     self.performSegue(withIdentifier: &quot;showHome&quot;, sender: nil)
   } 
}

答案2

得分: 0

你的方法 FeaturedPostsManager.shared.getFeaturedPosts 是异步的,问题可能就在这里。

你有更多选择,其中之一是按顺序调用 getFeaturedPosts,当达到10次调用后,你可以调用

self.performSegue(withIdentifier: "showHome", sender: nil)
英文:

I guess problem is that your method FeaturedPostsManager.shared.getFeaturedPosts is asynchronous.

You have more options one of them is that you will call getFeaturedPosts sequentially and when you reach 10 calls after that you'll call

self.performSegue(withIdentifier: &quot;showHome&quot;, sender: nil)

huangapple
  • 本文由 发表于 2020年1月3日 21:41:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/59579626.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定