zoukankan      html  css  js  c++  java
  • swift协议代理的使用以及解决循环引用问题

     

    这两天看了一下swift的协议代理, 大体思路和OC没什么区别, 但是按照官方的书本写出的协议代理, 发现会有内存泄露问题, 找了半天没有发现问题, 突然想起看系统类的协议代理的写法, 瞬间发现了问题, 不多废话了, 下面是代码.
    我建了一个single View application, 为了验证内存泄露, 我保留了xcode所给的viewController.swift,在storyboard中viewController前添加了一个 navigationController, 并且自己建了两个视图控制器: VC1.swift 和 VC2.swift, 由viewController 跳转至 VC1, 在VC1中设置delegate, 再跳转到VC2, 让VC2改变VC1的背景颜色, 然后一直返回到viewController, 看VC1 和 VC2 是否释放了内存;
    下面这是我的storyboard, 我在viewContronller 前面添加了一个navigationController:
    这是我的Main.storyboard

    下面是我的viewController里的代码:

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.title = "viewController"
    
            //实例化一个button, 添加点击事件
            let button = UIButton(type: UIButtonType.Custom)
            button.backgroundColor = UIColor.redColor()
            button.setTitle("点击跳转到VC1", forState: UIControlState.Normal)
            button.frame = CGRectMake(100, 100, 150, 100)
            button.addTarget(self, action: "buttonClicked", forControlEvents: UIControlEvents.TouchUpInside)
            self.view.addSubview(button)
        }
    
        //跳转到VC1
        func buttonClicked(){
            let vc_1 = VC1()
            self.navigationController?.pushViewController(vc_1, animated: true)
        }
    }
    
    

    这下面是VC1 中的代码:

    import UIKit
    
    // VC1 遵守changeColor协议, 并且实现协议中的方法
    class VC1: UIViewController, changeColor{
    
        var vc_2: VC2?   //定义一个VC2变量
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.view.backgroundColor = UIColor.orangeColor()
            self.title = "VC1"
    
            //实例化VC2, 并且设置delegate
            vc_2 = VC2()
            vc_2?.delegate = self
    
            let button = UIButton(type: UIButtonType.Custom)
            button.backgroundColor = UIColor.whiteColor()
            button.setTitle("点击跳转到VC2", forState: UIControlState.Normal)
            button.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
            button.frame = CGRectMake(100, 100, 150, 100)
            button.addTarget(self, action: "VC1buttonClicked", forControlEvents: UIControlEvents.TouchUpInside)
            self.view.addSubview(button)
        }
    
        //跳转到VC2
        func VC1buttonClicked(){
            self.navigationController?.pushViewController(vc_2!, animated: true)
        }
    
        //实现协议中的方法
        func changeColorWithColor(color color: UIColor) {
            self.view.backgroundColor = color
        }
    
        deinit{
            print("vc_1 的内存已释放 !")
        }
    }
    
    

    下面是我的VC2中的代码:

    import UIKit
    
    //声明一个协议, 让其继承(我也不知道该不该叫继承, 然而在这里并不重要) NSObjectProtocol, 只有这样才能在设置代理的时候前面添加weak
    protocol changeColor: NSObjectProtocol {
        func changeColorWithColor(color color: UIColor)
    }
    
    class VC2: UIViewController {
    
        //注意这里: changeColor为协议名, delegate前面必须有weak修饰, 如果没有weak修饰就会造成内存泄露, 而可以加weak的前提是, 这个协议必须继承 NSObjectProtocol, 这是我试验出来的, 目前来看, 应该是这样的
        weak var delegate: changeColor?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.view.backgroundColor = UIColor.whiteColor()
            self.title = "VC2"
    
            let button = UIButton(type: UIButtonType.Custom)
            button.backgroundColor = UIColor.redColor()
            button.setTitle("点击改变VC1的背景颜色", forState: UIControlState.Normal)
            button.frame = CGRectMake(100, 100, 200, 100)
            button.addTarget(self, action: "VC1buttonClicked", forControlEvents: UIControlEvents.TouchUpInside)
            self.view.addSubview(button)
        }
    
        func VC1buttonClicked(){
            //使用代理调用协议声明并且VC1已经实现的方法
            self.delegate?.changeColorWithColor(color: UIColor.cyanColor())
        }
    
        deinit{
            print("vc_2的内存已经释放 !")
        }
    }
    
    

    下面是返回至viewController后的打印信息:

    /*
    vc_1 的内存已释放 !
    vc_2的内存已释放 !
    */
    
  • 相关阅读:
    一致性哈希算法
    Discourse 的标签(Tag)只能是小写的原因
    JIRA 链接 bitbucket 提示错误 Invalid OAuth credentials
    JIRA 如何连接到云平台的 bitbucket
    Apache Druid 能够支持即席查询
    如何在 Discourse 中配置使用 GitHub 登录和创建用户
    Apache Druid 是什么
    Xshell 如何导入 PuTTYgen 生成的 key
    windows下配置Nginx支持php
    laravel连接数据库提示mysql_connect() :Connection refused...
  • 原文地址:https://www.cnblogs.com/luoxiaoxi/p/5362300.html
Copyright © 2011-2022 走看看