iOS开发

不要使用Runtime在分类中添加代理属性

2018-08-17  本文已影响6人  seasonZhu

最近因为封装的需要,我在Swift中的UITableView中添加了一个代理属性以便于我进行下拉与上拉的刷新的回调操作.

结果我发现,为其添加的代理属性导致了循环引用.
没错,就算你这个代理属性使用weak修饰,就算你在使用的过程怎么小心翼翼,这个代理的循环引用都是存在的.

为了验证其普遍性,我做了以下很没技术含量的代码测试,然后你就可以看到循环引用了

添加UIView代理属性的分类

import UIKit

private var delegateString = "UIViewRuntimeInterface"

// MARK: - 为UIView添加代理属性
extension UIView {
    weak var delegate: UIViewRuntimeInterface? {
        get {
            return objc_getAssociatedObject(self, &delegateString) as? UIViewRuntimeInterface
        }
        set {
            objc_setAssociatedObject(self, &delegateString, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

protocol UIViewRuntimeInterface: class {
    func uiViewRuntimeInterfaceMethod()
}

ViewController

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let button = UIButton(frame: CGRect(x: 0, y: 200, width: UIScreen.main.bounds.width, height: 22))
        button.setTitle("Push", for: .normal)
        button.setTitleColor(UIColor.black, for: .normal)
        button.addTarget(self, action: #selector(buttonAction(_ :)), for: .touchUpInside)
        view.addSubview(button)
    }

    @objc private func buttonAction(_ button: UIButton) {
        let secondVC = SecondController()
        navigationController?.pushViewController(secondVC, animated: true)
    }
}

SecondController

import UIKit

class SecondController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.white
        
        let aView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        aView.backgroundColor = UIColor.lightGray
        aView.center = view.center
        aView.delegate = self
        view.addSubview(aView)
    }
    
    deinit {
        print("SecondController被销毁了")
    }
}

extension SecondController: UIViewRuntimeInterface {
    func uiViewRuntimeInterfaceMethod() {
        print("哈哈哈")
    }
}

我个人的理解是runtime对分类添加的属性就是永远都是strong类型.
同时我使用OC干了同样的事情,OC中在分类中添加代理属性,那么引用也会造成循环引用.

所以,不要使用Runtime在分类中添加代理属性,而是使用Runtime在分类中添加使用Block或者Callback进行回调,这样是不会造成循环引用的.

通过继承添加属性这个当然是可以的.

上一篇下一篇

猜你喜欢

热点阅读