如何在Swift中的转义块内正确访问自我

时间:2018-02-17 00:18:04

标签: ios swift

我在下面的代码中遇到了一些崩溃。我认为崩溃是由块(LoadXZYAPI)转义和已经解除分配的ViewControllerA的访问属性引起的。因此,当strongSelf.data。*正在访问时,strongSelf返回nil或dealloc内存位置并导致崩溃。

每次尝试访问其属性(data。*)时,有没有办法防止此崩溃而不检查strongSelf?在不使LoadXZYAPI非转义的情况下,此方案中的最佳做法是什么?

提前致谢

class ViewControllerA {

        var data: [String: Any]?

        func loadData(){

            LoadXZYAPI() { [weak self] (data:Any?) in

                if let strongSelf = self {

                    strongSelf.data = data

                    DispatchQueue.global(qos:.default).asyc {

                        // process self.data
                        let imageData = GetImageData(data:strongSelf.data["image_name"])

                        if let data = data, let image = UIImage(data:imageData) {

                            DispatchQueue.main.async {
                                strongSelf.imageView = nil

                                strongSelf.imageView = CustomView(image: image) <-- Crashes randomly after this line
                                strongSelf.imageView!.width = strongSelf.map["width"] as? CGFloat
                                strongSelf.imageView!.height = strongSelf.map["height"] as? CGFloat
                                strongSelf.imageView!.backgroundColor = UIColor.init(hex: "#efefef")
                                strongSelf.imageViewWrapper.addSubview((strongSelf.imageView)!)
                                strongSelf.imageViewWrapper.bringSubview(toFront: (strongSelf.imageView)!)
                                strongSelf.imageView!.translatesAutoresizingMaskIntoConstraints = false
                                NSLayoutConstraint.activate([
                                    (strongSelf.imageView?.leadingAnchor)!.constraint(equalTo: (strongSelf.imageViewWrapper?.leadingAnchor)!),
                                    (strongSelf.imageView?.trailingAnchor)!.constraint(equalTo: (strongSelf.imageViewWrapper?.trailingAnchor)!),
                                    (strongSelf.imageView?.topAnchor)!.constraint(equalTo: (strongSelf.navigationController?.navigationBar.bottomAnchor)!),
                                    (strongSelf.imageView?.bottomAnchor)!.constraint(equalTo: (strongSelf.imageViewWrapper?.bottomAnchor)!),
                                    ])

                                self?.didUpdateImageView()
                            }
                        }
                    }
                }
            }
        }
    }

2 个答案:

答案 0 :(得分:1)

这应该是安全的:

func loadData(){

    LoadXZYAPI() { [weak self] (data:Any?) in

        //didn't bother putting a guard here since you don't need a strong ref here
        self?.data = data

        DispatchQueue.global(qos:.default).asyc {

            guard let strongSelf1 = self else {
                return
            }

            //use strongSelf1

            DispatchQueue.main.async {

                guard let strongSelf2 = self else {
                    return
                }

                //use strongSelf2
            }
        }
    }
}

答案 1 :(得分:-1)

实际上你必须在每个闭包中捕获弱自我,如果你假设在加载过程中某个时候可能会关闭viewController

func loadData(){

    LoadXZYAPI() { [weak self] (data:Any?) in

        guard let strongSelf = self else {
            return
        }

        strongSelf.data = data
        DispatchQueue.global(qos: .default).async { [weak self] in

                // process and manipulate self.data

                DispatchQueue.main.async { [weak self] in

                    // Update UI
                }
        }
    }
}