ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Swift 메모리 관리: ARC
    ios/Etc 2022. 3. 22. 15:06
    728x90

    ARC(Automatic Reference Counting)

    자동으로 참조 카운팅을 해주는 것 (+MRC(Manual Reference Counting): 수동으로 참조 카운팅을 하는 것)

    // 일반적인 클래스 선언
    class Person {
        let name: String
        
        init(name: String) {
        	self.name = name
        }
    }
    
    //ARC 클래스 선언
    class Person {
        let name: String
        
        init(name: String) {
        	self.name = name
        }
        
        deinit {
        	print("\(name)은 디이니셜됩니다.")
        }
    }

     

     

    ARC는 어떻게 동작할까

     

    강한 참조를 자동으로 카운트한다.

    • 강한 참조는 프로퍼티, 상수 또는 변수에 클래스 인스턴스를 할당하는 것을 강한 참조라고 한다.
    //강한 참조
    
    class Person {
    ...
    }
    
    let John: Person?
    var John2: Person?
    John = Person(name: "John Appleseed")
    • 인스턴스를 함수나 메서드에 인자로 전달하면 해당 블록이 실행되는 동안 참조 카운트가 증가하고 함수나 메서드가 종료되면 참조 카운트가 감소한다.
    struct Car {
    	func fixed(Fixer: Person){
        	print("\(Fixer)의 참조 카운트는 자동차를 고치는 동안 1 증가합니다.")
            print("\(Fixer)가 자동차를 고치는 중")
            print("\(Fixer)의 참조 카운트는 fixed 함수가 끝나면 1 감소합니다.")
        }
    }
    
    var John: Person?
    
    John = Person(name: "John Applessed")
    
    var hyundaiCar = Car()
    hyundaiCar.fixed(Fixer: John!)
    • 함수나 메서드, 클로저 등 코드 블럭 내에서 생성한 인스턴스는 당연히 해당 코드 블럭이 끝나면 참조 카운트가 감소한다.
    struct Car {
    	func fixed(Fixer: Person) {
        	print("\(Fixer.name)의 조수를 모집합니다.")
            let assistant = Person(name: "Steve Wozniak")
            print("\(Fixer.name)와 \(assistant.name)가 자동차를 고치는 중")
            print("\(Fixer.name)과 \(assistant.name)의 참조 카운트는 fixed 함수가 끝나면 1 감소합니다.")
        }
    }
    • 강한 참조가 없다면 deinit 메서드가 실행된 후 해당 인스턴스는 자동으로 메모리에서 할당 해제된다.
    • 강한 참조가 남아있다면 해당 인스턴스를 할당 해제하지 못한다.

     

    예제

     

    1.

    Code RC
    reference1 = Person(name: "John") 1
    reference2 = reference1 2
    reference3 = reference2 3
    reference1 = nil 2
    reference2 = nil 1
    reference3 = nil 0

    2.

    Code RC
    reference1 = Person(name: "John") 1
    reference2 = Person(name: "John") 1
    reference3 = Person(name: "John") 1
    reference1 = nil 0
    reference2 = nil 0
    reference3 = nil 0

    3.

    Code RC
    reference1 = Person(name: "John") 1
    reference2 = reference1 2
    reference1 = nil 1
    reference3 = reference1 1
    reference4 = reference2 2
    reference3 = nil 2

     

     

    강한 참조로만 구성하면 발생하는 문제

     

    class Person {
    	let name: String				                
        init(name:String) { self.name = name }			 
        var apartment: Apartment?	
        deinit { print("\(name) is being deinitialized") }
    }													  
    
    class Apartment {									 
    	let unit: String								 
    	init(unit: String) { self.unit = unit }
        var tenant: Person?								  
        deinit { print("Apartment \(unit) is being deinitialized") }
    
    
    //MARK: 강한 참조 구현
    
    //인스턴스 생성
    var john: Perons?  
    var number73: Apartment?
    
    //강한 참조
    john = Person(name: "John")
    number73 = Apartment(unit: "4A")
    
    //각 클래스 내부에 있는 다른 인스턴스가 서로를 강한 참조
    john!.apartment = number73
    number73!.tenant = john
    
    //인스턴스는 끊어졌는데 내부의 apartment가 number73을 참조하고 있고 Person이 john을 참조하고 있어 메모리에서 할당이 해제되지 않음
    john = nil
    number73 = nil

     

    해결방법

     

    약한 참조

    • 참조하는 인스턴스가 메모리에서 해제될 수도 있다는 것을 예상해 인스턴스를 참조하더라도 참조 횟수를 늘리지 않는 참조
    • 프로퍼티나 변수 앞에 weak 을 추가하여 사용 ( weak var tenant: Person?)
    • 약한 참조는 항상 변수로 선언해야 한다. (상수로 선언하면 안된다.)
    • 약한 참조는 항상 옵셔널로 선언해야 한다.

    미소유 참조

    • 참조하는 인스턴스가 항상 메모리에 존재할 것이라는 것을 예상해 인스턴스를 참조하더라도 참조 횟수를 늘리지 않는 참조
    • 프로퍼티나 변수 앞에 unowned를 추가하여 사용 ( unowned var tenant: Person)
    • 참조하는 인스턴스가 메모리에서 해제되더라도 자동으로 nil을 할당해주지 않음
    • 메모리에서 해제된 인스턴스에 접근하려 하면 잘못된 메모리 접근으로 런타임 오류가 발생 -> 프로세스가 강제로 종료됨

     

    참조

    야곰의 스위프트 프로그래밍

    iOS와 OS X의 메모리 관리와 멀티스레딩 기법 - OSXDEV 저

    빅 너드 랜치의 스위프트 프로그래밍

    Ojective-C 개발자를 위한 SWIFT 김근영 저

    728x90

    'ios > Etc' 카테고리의 다른 글

    @escaping  (0) 2022.05.14
    Concurrency & Threading  (0) 2022.04.08
    GoF Design Pattern  (0) 2022.03.06
    Cocoa란?(Feat. iOS, macOS)  (0) 2022.03.05
    Life Cycle  (0) 2022.02.23

    댓글

oguuk Tistory.