목차

iOS Strong & Weak Reference (ARC)

Swift 기본 참조 타입. 참조하는 인스턴스의 소유권을 가짐.

  • 참조 카운트를 1 증가
  • 참조가 유지되는 동안 인스턴스는 메모리에서 해제되지 않음
  • 순환 참조 발생 시 해제 불가능한 상황 발생
class Person {
    var name: String
    var pet: Pet? // 기본적으로 strong reference

    init(name: String) {
        self.name = name
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

class Pet {
    var name: String
    var owner: Person? // 기본적으로 strong reference

    init(name: String) {
        self.name = name
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

// 강한 참조 순환 발생
var person: Person? = Person(name: "Alice")
var pet: Pet? = Pet(name: "Bobby")

person?.pet = pet
pet?.owner = person

// 강한 참조로 인해 두 객체 모두 메모리에서 해제되지 않음
person = nil
pet = nil

//person과 pet 내부의 pet, owner가 참조를 가지고 있으므로 해제가 안됨


//만일 헤제를 하고 싶다면 아래의 순서대로 수동으로 끊어줘야함

// 강한 참조를 수동으로 해제
person?.pet = nil // person -> pet 연결 끊기
pet?.owner = nil  // pet -> person 연결 끊기

// 이제 두 객체는 메모리에서 정상적으로 해제됨
person = nil
pet = nil

// 출력:
// Alice is being deinitialized
// Bobby is being deinitialized

  • weak 키워드로 선언
  • 참조 카운트를 증가시키지 않음
  • 항상 Optional 타입이어야 함 — 참조 대상이 해제되면 자동으로 nil
  • 주로 부모-자식 관계에서 자식이 부모를 약하게 참조할 때 사용
class Person {
    var name: String
    weak var pet: Pet? // 약한 참조

    init(name: String) {
        self.name = name
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

class Pet {
    var name: String
    var owner: Person? // 강한 참조

    init(name: String) {
        self.name = name
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

// 약한 참조로 강한 순환 참조 방지
var person: Person? = Person(name: "Alice")
var pet: Pet? = Pet(name: "Bobby")

person?.pet = pet // person이 pet을 약하게 참조
pet?.owner = person // pet이 person을 강하게 참조

// person과 pet 모두 메모리에서 정상적으로 해제됨
person = nil
pet = nil

// 출력:
// Alice is being deinitialized
// Bobby is being deinitialized

특징StrongWeak
참조 카운트 증가
객체 생명 주기강하게 유지대상 해제 시 자동 nil
옵셔널 여부불필요항상 Optional
사용 사례일반적인 소유권 관계순환 참조 방지, 비소유권 관계