Taehyeon-Kim / SeSAC

☀️ SeSAC Daily Reporting
27 stars 0 forks source link

[220905] TIL #122

Open Taehyeon-Kim opened 2 years ago

Taehyeon-Kim commented 2 years ago

ARC

메모리 구조

ARC

RC (참조 횟수)

생성/해제

var user: User? = User(name: "고래밥") // User: RC 1
var guild: Guild? = Guild(name: "SeSAC") // Guild: RC 1

guild = nil // Guild: RC 0
user = nil // User: RC 0

/*
User init
Guild init
Guild deinit
User deinit
*/
var user: User? = User(name: "고래밥") // User: RC 1
var guild: Guild? = Guild(name: "SeSAC") // Guild: RC 1

user?.guild = guild // Guild: RC 2
guild?.owner = user // User: RC 2

guild = nil // Guild: RC 1
user = nil // User: RC 1

/*
User init
Guild init
*/

// ==> 순환 참조 발생

해결

순환 참조인 녀석을 먼저 nil

var user: User? = User(name: "고래밥") // User: RC 1
var guild: Guild? = Guild(name: "SeSAC") // Guild: RC 1

user?.guild = guild // Guild: RC 2
guild?.owner = user // User: RC 2

guild?.owner = nil // User: RC 1

guild = nil // Guild: RC 1
user = nil // User: RC 0 -> user deinit -> Guild: RC 0

/*
User init
Guild init
User deinit
Guild deinit
*/

수동으로 해결하기 어렵다.

weak, unowned keyword

ARC + delegate

protocol MyDelegate: AnyObject {
    func sendData(_ data: String)
}
protocol BDelegate: AnyObject {
  func method()
}

class A: BDelegate {

  lazy var b: B = {
    let view = B()
    view.delegate = self
    return view
  }()

  func method() {
    // code
  }

}

class B {

  weak var delegate: BDelegate?

  func dismiss() {
    delegate?.method()
  }

}

// var A: A? = A()
// A?.b
// A.nil

/*
weak키워드로 참조를 약하게 만들지 않으면 A, B의 인스턴스는 해제되지 않는다.
*/

ARC + Closure

import UIKit

class User {
    var nickname = "JACK"

    lazy var introduce: () -> String = { [weak self] in
        return "저는 \(String(describing: self?.nickname))입니다."    // self로 접근하기 때문에 순환 참조 발생
    }

    init() {
        print("User init")
    }

    deinit {
        print("User deinit")
    }
}

var user: User? = User()
user?.introduce()       // RC + 1
user = nil

// User init
// User deinit

값 캡처

func myClosure() {

    var number = 0
    print("1: \(number)")

    let closure: () -> Void = { [number] in  // 값 캡처, 값 타입 - 복사, 클로저 안에서는 값이 영향을 받지 않는다.
        print("closure: \(number)")
    }

    closure()

    number = 100
    print("2: \(number)")

    closure()
}

myClosure()

/*
1: 0
closure: 0
2: 100
closure: 0
*/
Taehyeon-Kim commented 2 years ago

Swift에서 메모리를 어떻게 하죠?

weak와 unowned의 차이는 무엇인가?

Taehyeon-Kim commented 2 years ago

메모리에서 인스턴스가 해제되었는지 어떻게 아나요?