简单的简单代码。奇怪的行为

时间:2016-11-15 03:48:30

标签: ios swift multithreading concurrency grand-central-dispatch

我是gcd和多线程/并发/并行的新手。我编写了这个示例项目来测试一些东西。我有3种方法,一个图像网址列表,以及界面中的imageView。

每种方法基本上都是相同的,只有很小的变化。

loadAllImagesSlow()遍历图像网址,从每个网址创建NSData,创建UIImage并将imageView的图像设置为该图像。

loadAllImagesFast()将整个任务调度到全局并发队列。

newMethod()遍历图像URL并将每个任务分派到全局并发队列。这是最快的! :D令人兴奋的东西。对我来说无论如何。

当我运行loadAllImagesFast或newMethod时,我看到界面快速循环显示每个图像,结束于最后一个。但对于loadAllImagesSlow,我没有看到任何图像;只有最后一张图片出现在最后。

我相信loadAllImagesSlow正在主线程(串行队列)上运行,因为当我点击屏幕时我没有得到响应(其他功能不会阻止UI)。但由于它是一个串行队列,我不明白为什么imageView不能一次显示一个图像。由于主队列是串行的,所以应该在下面的代码之前执行所有操作。但是,在设置imageView的图像时不会发生这种情况。

为什么会有这样的想法?我不需要这个特定的项目;我只是想了解这种行为。

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    var urlArray = [

        "https://img0.ndsstatic.com/wallpapers/76df262f429c799124461286c5ee64b1_large.jpeg",
        "https://www.walldevil.com/wallpapers/a74/olivia-wilde-women-actresses-green-eyes-ponytails.jpg",
        "https://richestcelebrities.org/wp-content/uploads/2014/11/Olivia-Wilde-Net-Worth.jpg",
        "https://cdn.pcwallart.com/images/olivia-wilde-wallpaper-3.jpg",
        "https://kingofwallpapers.com/olivia-wilde/olivia-wilde-006.jpg",
        "https://img0.ndsstatic.com/wallpapers/b39ca6a58368a76a92d56739d6e2da31_large.jpeg"

    ]


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleTap))
        self.view.addGestureRecognizer(tapGesture)


        print("starting")
        self.loadAllImagesSlow()

    }

    func handleTap(sender: UITapGestureRecognizer) {
        print("tap")
    }


    func loadAllImagesSlow() { // takes around 4 seconds. UI is unresponsive throughout. Only last image gets shown

        let startTime = Date()
        for each in self.urlArray {

            let url = URL(string: each)

            do {

                let data = try Data(contentsOf: url!)
                self.imageView.image = UIImage(data: data)

            } catch {
                print("error")
            }


        }
        let endTime = Date()
        let executionTime = endTime.timeIntervalSince(startTime)
        print("Execution time: \(executionTime)")
    }


    func loadAllImagesFast() { // takes around 4 seconds, but UI is responsive! Cycles through the images!

        DispatchQueue.global(qos: .userInitiated).async {

            let startTime = Date()


            for each in self.urlArray {

                let url = URL(string: each)

                do {

                    let data = try Data(contentsOf: url!)

                    DispatchQueue.main.async {
                        self.imageView.image = UIImage(data: data)
                    }

                } catch {
                    print("error")
                }


            }

            let endTime = Date()
            let executionTime = endTime.timeIntervalSince(startTime)
            print("Execution time: \(executionTime)")

        }


    }


    func newMethod() { // much much faster than 'loadAllImagesFast'

        // This method harnesses the power of the concurrent queue by dispatching lots of smaller tasks that run concurrently, rather than dispatching one large task that runs concorruntly alongside nothing else in that queue; essentially, sequientially, on a seaprate queue.

        for each in self.urlArray {

            DispatchQueue.global(qos: .userInitiated).async {
                let url = URL(string: each)

                do {
                    let data = try Data(contentsOf: url!)

                    DispatchQueue.main.async {
                        self.imageView.image = UIImage(data: data)
                    }

                } catch {
                    print("error")
                }
            }


        }


    }


}

0 个答案:

没有答案