Ios 调度组在工作完成前通知

Ios 调度组在工作完成前通知,ios,swift,multithreading,Ios,Swift,Multithreading,我是苹果GCD的新手,对调度组有问题。 因此,我试图在post完全初始化后将post附加到地图。在post.init内部,有一个URLSession从url下载UIImage。但即使在下载完成之前,group.notify也会被触发。我真的找不出原因是什么。下面是代码。我真的很感激任何建议或帮助!谢谢 // ViewController.swift let group = DispatchGroup ... ... group.enter() DispatchQueue.global(qos:

我是苹果GCD的新手,对调度组有问题。 因此,我试图在post完全初始化后将post附加到地图。在
post.init
内部,有一个
URLSession
从url下载
UIImage
。但即使在下载完成之前,
group.notify
也会被触发。我真的找不出原因是什么。下面是代码。我真的很感激任何建议或帮助!谢谢

// ViewController.swift
let group = DispatchGroup
...
...

group.enter()
DispatchQueue.global(qos: .userInitiated).async {
    post = Post(values: post)
    self.posts[postId] = post
    group.leave()
}

group.notify(queue: DispatchQueue.main, execute: {
    print("notify:: \(post?.picture)") // This prints out nil, when it shouldn't.
    self.addPostToMap(post!, at: location!)
})

// Post.swift
class Post {
    var picture: UIImage?
    var thumbnail: UIImage?
    init(values: [String: Any]) {
        ...
        URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in 
            DispatchQueue.main.async {
                self.picture = UIImage(data: data!)
                self.thumbnail = Util.resizeImage(image: self.picture!, targetSize: CGSize(width: 50, height: 50))
            }

        }).resume()

    }

}

init中的完成处理程序(值:)仅在任务完成时触发,无论何时。但是,在调用.resume()之后,代码将继续执行,这意味着init将退出,并且您的group.notify块将立即被调用

你可以用不同的方法处理这个问题。一种方法是为Post类设置委托协议,并将ViewController设置为该委托。在完成处理程序中,您可以调用一个函数(为了参数起见,将其调用为didfish()),该函数将告诉视图控制器任务已完成。您可以将通知包装到该函数中

但是,如果这样做,我会将dataTask从init函数中去掉。原因是委托通常声明为隐式展开的选项,并从创建类中设置。因此,初始化类时,在调用委托回调时,委托可能不会引用任何内容

因此,结构如下:

// ViewController.swift
class ViewController : UIViewController, PostDelegate {
    let group = DispatchGroup
    ...
    ...

    group.enter()
    DispatchQueue.global(qos: .userInitiated).async {
        post = Post(values: post)
        post.delegate = self
        post.getImage() // New function
        self.posts[postId] = post
        group.leave()
    }

    ....

    func didFinish() -> Void {
        group.notify(queue: DispatchQueue.main, execute: {
            print("notify:: \(post?.picture)")
            self.addPostToMap(post!, at: location!)
    })

    ....

Protocol PostDelegate {
    func didFinish() -> Void
}

// Post.swift
class Post {
    var delegate : PostDelegate!
    var picture: UIImage?
    var thumbnail: UIImage?
    init(values: [String: Any]) {
    ...
    }

    func getImage() -> Void {
        URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in 
            DispatchQueue.main.async {
                self.picture = UIImage(data: data!)
                self.thumbnail = Util.resizeImage(image: self.picture!, targetSize: CGSize(width: 50, height: 50))
                if delegate != nil {
                    delegate.didFinish() // Tell the delegate you are done
                }
            }

        }).resume()

    }

}

希望这是有意义的,更重要的是,它有帮助

谢谢您的回复,但是取出notify会有问题,因为我现在无法从
didfish
访问变量
post
location
。有什么建议吗?事实上是我做的!我通过委托方法传递了变量。谢谢