Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 低分辨率图像加载时间过长_Swift_Nsurlsession_Dispatch Async - Fatal编程技术网

Swift 低分辨率图像加载时间过长

Swift 低分辨率图像加载时间过长,swift,nsurlsession,dispatch-async,Swift,Nsurlsession,Dispatch Async,使用Facebook Graph API,我检索到了一个指向200x200个人资料图片的字符串URL,该图片要显示在UIImageView中。我成功地做到了这一点,但我注意到,图像显示在屏幕上可能需要长达10秒的时间。有谁能给我一些关于如何优化它的建议(没有双关语的意思) override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) NSURLSession.sharedSession()

使用Facebook Graph API,我检索到了一个指向
200x200
个人资料图片的字符串URL,该图片要显示在
UIImageView
中。我成功地做到了这一点,但我注意到,图像显示在屏幕上可能需要长达10秒的时间。有谁能给我一些关于如何优化它的建议(没有双关语的意思)

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: self.profilePictureUrl)!, completionHandler: { (data, response, error) ->
        Void in
        self.profilePictureImageView.image = UIImage(data: data!)
        self.profilePictureImageView.layer.cornerRadius = self.profilePictureImageView.frame.size.width / 2;
        self.profilePictureImageView.clipsToBounds      = true

        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            self.view.addSubview(self.profilePictureImageView)
        })

    }).resume()
}

您应该将所有
UIView
调用(因此您在
UIImageView
上设置的任何内容)移动到主线程上,因为UIKit在大多数情况下都不是线程安全的。您可以在后台线程上实例化
UIImage
,以优化性能,因此请尝试以下操作:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    let url = NSURL(string: self.profilePictureUrl)!

    NSURLSession.sharedSession().dataTaskWithURL(
        url,
        completionHandler: { [weak self] (data, response, error) -> Void in
            guard let strongSelf = self else { return }

            // create the UIImage on the background thread
            let image = UIImage(data: data!)

            // then jump to the main thread to modify your UIImageView
            dispatch_async(dispatch_get_main_queue(), { [weak self] () -> Void in
                guard let strongSelf = self else { return }

                let profilePictureImageView = strongSelf.profilePictureImageView

                profilePictureImageView.image = image
                profilePictureImageView.layer.cornerRadius = profilePictureImageView.frame.size.width / 2;
                profilePictureImageView.clipsToBounds = true

                strongSelf.view.addSubview(profilePictureImageView)
            })
        }
    ).resume()
}

还请注意,我已将您对
self
的引用
弱化了。无法保证用户在调用完成例程时没有解除启动此代码的视图控制器,因此您希望确保没有保留对
self
的强引用。这允许视图控制器在用户解除它时解除分配,然后完成例程提前返回,而不做任何不必要的工作。

您应该将所有
UIView
调用(因此您在
UIImageView
上设置的任何内容)移动到主线程上,因为大部分情况下UIKit都不是线程安全的。您可以在后台线程上实例化
UIImage
,以优化性能,因此请尝试以下操作:

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    let url = NSURL(string: self.profilePictureUrl)!

    NSURLSession.sharedSession().dataTaskWithURL(
        url,
        completionHandler: { [weak self] (data, response, error) -> Void in
            guard let strongSelf = self else { return }

            // create the UIImage on the background thread
            let image = UIImage(data: data!)

            // then jump to the main thread to modify your UIImageView
            dispatch_async(dispatch_get_main_queue(), { [weak self] () -> Void in
                guard let strongSelf = self else { return }

                let profilePictureImageView = strongSelf.profilePictureImageView

                profilePictureImageView.image = image
                profilePictureImageView.layer.cornerRadius = profilePictureImageView.frame.size.width / 2;
                profilePictureImageView.clipsToBounds = true

                strongSelf.view.addSubview(profilePictureImageView)
            })
        }
    ).resume()
}
还请注意,我已将您对
self
的引用
弱化了。无法保证用户在调用完成例程时没有解除启动此代码的视图控制器,因此您希望确保没有保留对
self
的强引用。如果用户解除了视图控制器,并且完成例程提前返回而不做任何不必要的工作,则允许视图控制器解除分配。

此代码是非法的:

NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: self.profilePictureUrl)!, completionHandler: { (data, response, error) ->
    Void in
    self.profilePictureImageView.image = UIImage(data: data!)
住手!您正在背景线程上设置UIImageView的图像。不,UIKit不是线程安全的。您必须进入主线程才能执行此操作。(您最终会进入代码中的主线程,但为时已晚。)

此代码是非法的:

NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: self.profilePictureUrl)!, completionHandler: { (data, response, error) ->
    Void in
    self.profilePictureImageView.image = UIImage(data: data!)

住手!您正在背景线程上设置UIImageView的图像。不,UIKit不是线程安全的。您必须进入主线程才能执行此操作。(您最终会进入代码中的主线程,但这样做太晚了。)

可能尝试在异步调用之外添加子视图,然后在完成块中设置子视图的映像?可能尝试在异步调用之外添加子视图,然后在完成块中设置子视图的图像?非常感谢所有这些改进。我很好奇-您是否有意创建了两个对
strongSelf
的引用?我之所以问这个问题,是因为Xcode对其中一个声明给出了警告。是的,您需要两个对
strongSelf
的引用,因为每个回调都可能跳转一个线程。如果Xcode抱怨,您将不得不更改其中一个变量名,例如,使用内部变量名
strongSelfInner
。非常感谢您所做的所有改进。我很好奇-您是否有意创建了两个对
strongSelf
的引用?我之所以问这个问题,是因为Xcode对其中一个声明给出了警告。是的,您需要两个对
strongSelf
的引用,因为每个回调都可能跳转一个线程。如果Xcode抱怨您必须更改其中一个变量名,例如,使用内部变量名
strongSelfInner