Swift의 Memory - weak / unowned

June·2023년 3월 14일
0

Swift

목록 보기
10/18
post-thumbnail

메모리 누수의 해결 방법

  • weak(약한 참조)
  • unowned(비소유 참조)

    약한 참조와 비소유 참조 모두 참조는 하되, 가리키는 인스턴스의 숫자(RC)를 올라가지 않게 하는 방법.


weak (약한 참조)

  • 참조하고 있던 인스턴스가 사라지면 nil로 초기화됨(nil 자동할당)
  • nil로 할당할 수 있어야 하기 때문에 상수(let)선언 불가능
  • nil을 할당할 수 있어야 하기 때문에 Optional타입이어야 함
  • 소유자에 비해 짧은 생명주기를 가진 인스턴스 참조시 주로 사용함
  • 인스턴스 nil로 확인 가능, nil인 경우 작업 중단 가능
  • 실제 프로젝트에서 unowned보다 더 많이 사용됨
class Nation {
    var name: String
    weak var person: Citizen?    // 약한 참조
    
    init(name: String) {
        self.name = name
    }
    
    deinit {
        print("\(name) 메모리 해제")
    }
}


class Citizen {
    var name: String
    weak var state: Nation?    // 약한 참조
    
    init(name: String) {
        self.name = name
    }
    
    deinit {
        print("\(name) 메모리 해제")
    }
}

var me: Citizen? = Citizen(name: "June")
var korea: Nation? = Nation(name: "SouthKorea")

// 강한 참조 사이클이 일어나지 않는다.
me?.state = korea
korea?.person = me

// 메모리 해제 ok (이 경우엔 한쪽만 weak로 선언해도 됨)
me = nil
korea = nil

unowned (비소유 참조)

  • 참조하고 있던 인스턴스가 사라져도 nil로 초기화되지 않음(nil을 자동할당하지 않음)
  • 상수와 변수 선언 모두 가능
  • Optional(Swit 5.3 이후로 가능해짐)과 non-Optional 모두 가능
  • 소유자보다 인스턴스의 생명주기가 더 길거나 같은 경우에 사용
  • 인스턴스로 nil확인 불가, 실제 인스턴스 해제시 에러 발생함
  • weak보다 조금 더 빠름
class Nation {
    var name: String
    unowned var person: Citizen?    // 비소유 참조
    
    init(name: String) {
        self.name = name
    }
    
    deinit {
        print("\(name) 메모리 해제")
    }
}


class Citizen {
    var name: String
    unowned var state: Nation?    // 비소유 참조
    
    init(name: String) {
        self.name = name
    }
    
    deinit {
        print("\(name) 메모리 해제")
    }
}

var me: Citizen? = Citizen(name: "June")
var korea: Nation? = Nation(name: "SouthKorea")

// 강한 참조 사이클이 일어나지 않는다.
me?.state = korea
korea?.person = me

// 메모리 해제 ok (이 경우엔 한쪽만 unowned로 선언해도 됨)
me = nil
korea = nil



📌 nil 짚고 넘어가기

nil은 실제로 값이 없는게 아니고, 값이 없음을 나타내는 키워드.
nil은 값이 없음을 나타내는 열거형에서의 하나의 케이스일 뿐이다.
nil이 있다는 것은 열거형이 존재한다는 뜻.

📌 unowned에서 인스턴스 해제시 에러가 나는 이유?

weak는 nil로 초기화되기 때문에 에러가 나지 않는다.
하지만 unowned는 nil로 초기화되지 않기 때문에, 즉 실제로 메모리 주소에 값이 존재하지 않기 때문에 에러가 나는 것이다.

profile
안다고 착각하지 말기

0개의 댓글