Swift 内存管理

简介

不管什么语言,内存管理始终是重中之重,所以作为苹果推荐使用的后起之秀Swift也不例外,Swift的内存管理是使用的ARC

Automatic Reference Counting: Swift uses Automatic Reference Counting (ARC) to track and manage your app’s memory usage. In most cases, this means that memory management “just works” in Swift, and you do not need to think about memory management yourself. ARC automatically frees up the memory used by class instances when those instances are no longer needed.

iOS5之前,iOS的内存管理是MRC,那时候的内存管理全靠程序猿。iOS5之后才有了ARC,也是苹果一大改进我们一般情况下不需要对对象的release进行特别管理(除通知/Timer/Block等)。 iOS ARC和MRC区别


工作机制

  • Swift内存管理和OC一样: 管理引用类型的内存, 不会管理值类型, 值类型不需要管理
    • 采用自动引用计数来管理内存, 默认情况下所有的引用都是强引用
    • 当有一个强引用指向某一个对象时,该对象的引用计数会自动+1
    • 当该强引用消失时,引用计数会自动-1

一般循环引用

  • 👆也介绍了,Swift使用的是ARC,它会自动帮助我们管理内存的
  • But 我们开发中,经常会出现有耦合的两个类相互持有对方属性,造成循环引用的问题,看👇:
    • Master -> Dog 有一个强引用
    • Dog -> Master 有一个强引用
    • 手动给对象置nil (没有deinit)
// master 主人
class Master: NSObject {

    // 持有一条狗
    var dog: Dog?
    
    deinit {
        print("---------Master deinit---------")
    }
    
}
---------------------------------------------------------------
// Dog 狗狗
class Dog: NSObject {

    // 狗狗有个主人
    var master: Master?
    
    deinit {
        print("---------Dog deinit---------")
    }
    
}
---------------------------------------------------------------
class ViewController: UIViewController {

    var d: Dog?
    var m: Master?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 狗狗
        d = Dog()
        // 主人
        m = Master()
        
        // 给狗狗个主人
        d?.master = m
        // 给主人个狗狗
        m?.dog = d
        
        // 手动置nil
        d = nil
        m = nil
        
    }
}

解决问题

  • weak: 和OC中的__weak一样是一个弱引用.当指向的对象销毁时,会自动将指针指向nil
  • unowned: 和OC中的__unsafe_unretained.当对象销毁时依然指向原来的内存地址, 该修饰不能指向nil

unownedweak是有区别的,看看官方的解释:
“If the captured reference will never become nil, it should always be captured as an unowned reference, rather than a weak reference.”

如果该引用不会变成nil,那么你应该使用unowned引用,而不是weak。所以unowned其实有点儿像Objective - C里面的unsafe_unretained。而且这里有一点需要注意:不要使用weak去修饰一个let,因为该引用之后会变,所以只能是var,这一点在官方文档里面也有提示:
“Weak references must be declared as variables, to indicate that their value can change at runtime. A weak reference cannot be declared as a constant.”

// Dog 狗狗
class Dog: NSObject {

    // 狗狗有个主人
    weak var master: Master?
    
    deinit {
        print("---------Dog deinit---------")
    }
    
}
---------------------------------------------------------------
---------Master deinit---------
---------Dog deinit---------


闭包循环引用

Swift中的闭包(closure)Objective - C中的block一样,会引起循环引用,从而导致内存泄露。解决办法👇:

  • 使用weak修饰变量, 打破强引用, 因为使用weak修饰的变量有一次变成nil的机会
  • 使用[weak self] 修饰闭包原理跟__weak类似, 这样在闭包中使用self, 就是弱引用
  • 使用[unowned self ] 修饰闭包, 跟__unsafe_unretained类似, 不安全
class NextViewController: UIViewController {

    var completionHandler:((_ name: String)->())?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = UIColor.purple
        view.alpha = 0.4
        
        //0. 循环引用
        self.retainMethod()
        
        //1. weak var weakSelf = self weak
        self.weakSelfMethod1()
        
        //2. [weak self] 跟OC __weak 相似  [weak self]
        self.weakSelfMethod2()
        
        //3. [unowned self] 跟 _unsafe_unretained 类似  不推荐使用
        self.unownedMethod()
    }

    func retainMethod() {
        networkWithPath(path: "www.baidu.com", param: ["name":"haha"]) { (name) in
            print("\(self.view)")
        }
    }
    
    func weakSelfMethod1 () {
        
        weak var weakSelf = self
        
        networkWithPath(path: "www.baidu.com", param: ["name":"haha"]) { (name) in
            
            print("\(String(describing: weakSelf?.view))")
            
        }
    }
    
    func weakSelfMethod2(){
        
        networkWithPath(path: "www.baidu.com", param: ["name":"haha"]) { [weak self] (name) in
            print("\(String(describing: self?.view))")
        }
    }
    
    func unownedMethod() {
        networkWithPath(path: "www.baidu.com", param: ["name":"haha"]) { [unowned self](name) in
            print("\(self.view)")
        }
    }
    
    func networkWithPath(path: String, param:[String: String], completionHandle:@escaping (_ name: String)->())->(){
        self.completionHandler = completionHandle
        self.completionHandler!("hello")
    }
    
    deinit {
        print("---------- NextViewController deinit ----------")
    }
    

}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 不管什么语言,内存管理始终是重中之重,所以Swift也不例外 Swift采用了和Objective - C相同的A...
    庸者的救赎阅读 3,917评论 8 13
  • Swift使用自动引用计数(ARC)机制来处理内存。通常情况下,Swift内存管理机制会自动管理内存,无须我们考虑...
    透支未来阅读 293评论 0 2
  • 之前我在CSDN上写过一篇博客:OC内存管理、ARC、property属性、__strong、__weak、__b...
    ShayneFcf阅读 640评论 0 4
  • 内存管理 ARC是Swift默认的内存管理机制,其针对堆上的对象,由编译器自动生成操作引用计数的指令(retain...
    AAup阅读 622评论 0 1
  • 当一个人出生时,这个世界便有人为他付出,从衣食住行,到琴棋书画,都有人在为他无私奉献,虽然这付出不一定是永远的,但...
    浅思念阅读 123评论 0 0