ariedaze
사과농장
ariedaze
전체 방문자
오늘
어제
  • 분류 전체보기 (18)
    • IOS (6)
    • Swift (5)
    • WWDC (2)
    • Combine (4)
    • 치타핏 개발일기 (1)
    • FOREST (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • 사과농장에 오신걸 환영합니다🥳

인기 글

태그

  • 새싹
  • WWDC21
  • Apple
  • combine
  • 개발
  • Swfit
  • 치타핏
  • await
  • swift
  • iOS앱
  • async
  • cheetahfit
  • WWDC
  • swft
  • ios
  • iOS앱개발
  • 앱개발

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ariedaze

사과농장

Swift | 강한 참조와 약한 참조! 순환 참조 사이클 해결방법
Swift

Swift | 강한 참조와 약한 참조! 순환 참조 사이클 해결방법

2021. 9. 1. 11:24

🦖 Strong Reference Cycle이란?

class Person {
	var name = "Ahyeon"
	var car: Car?
	deinit {
		print("person deinit")
	}
}

class Car {
	var model: String
	var lesee: Person?

	init(model: String) {
		self.model = model
	}
	deinit {
		print("car deinit")
	}
}

Person class는 Car 속성, Car class는 Person 속성을 가지고 있다.

var person: Person? = Person()
var rentedCar: Car? = Car(model: "Benz")

person과 rentedCar는 각각의 Person, Car 인스턴스에 강한 참조로 연결 된다. 이 시점에 각각 참조카운트는 1이다.

person?.car = rentedCar
rentedCar?.lessee = person

이 코드로 car속성과 retedCar인스턴스가 강한 참조로 연결되고 lessee 속성과 person인스턴스가 강한 참조로 연결된다.

 

 

 

PersonInstance와 CarInstance의 참조카운트가 2로 증가한다.

person = nil
rentedCar = nil

person변수에 nil을 할당하여 소유권을 포기하고 그 후 rentedCar 변수에 nil을 할당하여 소유권을 포기해보자.

 

 

 

소유권을 포기했지만 참조카운트가 1이상이기 때문에 메모리에서 사라지지 않는다. 두 인스턴스의 속성이 서로를 소유하고 있기 때문이다. nil로 인해 두 인스턴스에 접근할 방법이 없기때문에 메모리를 해지할 방법이 없다.

이렇게 강한 참조 때문에 인스턴스를 제대로 해지할 수 없는 경우를 강한 참조 사이클(Strong Reference Cycle) 이라고 한다. ARC는 메모리 관리를 자동으로 해주지만 강한 참조 사이클을 해결하지는 못한다.

따라서 강한 참조 사이클은 약한(Weak) 참조, 비소유(Unowned) 참조를 사용해서 해결한다.

🐇 Weak Reference

강한 참조와 달리 약한 참조는 인스턴스를 참조하지만 소유하진 않으므로 참조 카운트가 증가하지 않는다.
대상 인스턴스를 참조하고 있는 중 언제든 메모리에서 사라질 수 있다. 따라서 소유자에 비해서 짧은 생명주기를 가진 인스턴스를 참조할 때 사용한다.

Syntax

weak var name: Type?

약한 참조는 항상 옵셔널 형식으로 선언한다. 그리고 var 키워드 앞에 weak 키워드를 선언한다. 참조하고 있는 인스턴스가 해제되면 ARC 는 자동으로 nil로 초기화 한다.

class Person {
	var name = "Ahyeon"
	weak var car: Car?
	deinit {
		print("person deinit")
	}
}

class Car {
	var model: String
	weak var lesee: Person?

	init(model: String) {
		self.model = model
	}
	deinit {
		print("car deinit")
	}
}

weak 이 붙은 속성은 약한 참조로 선언되고 인스턴스를 참조하지만 소유하진 않는다. 따라서 강한 참조 사이클이 생기지않는다.

var person: Person? = Person()
var rentedCar: Car? = Car(model: "Benz")

person?.car = rentedCar
rentedCar?.lessee = person

person = nil

이렇게 하면 메모리 누수 없이 코드를 짤 수 있다.

🤔 Unowned Reference

비소유 참조도 약한 참조와 같은 방식으로 속성을 참조한다. 하지만 옵셔널이 아니라 비옵셔널로 선언한다. ARC는 비소유 참조를 nil로 설정하지 않는다. 따라서 unowned 는 참조하는 객체의 메모리가 해제된 상태에서 접근하면 bad access에러가 발생한다.
**비옵셔널로 선언해야할 때나, 인스턴스의 생명주기가 소유자와 같거나 더 긴 경우에 사용한다. **

Syntax

unowned var name: Type

unowned 키워드를 사용한다.

class Person {
	var name = "Ahyeon"
	var car: Car?
	deinit {
		print("person deinit")
	}
}

class Car {
	var model: String
	unowned var lesee: Person

	init(model: String, lessee: Person) {
		self.model = model
		self.lessee = lessee
	}
	deinit {
		print("car deinit")
	}
}

var person: Person? = Person()
var rentedCar: Car? = Car(model: "Benz", lessee: person!)

person?.car = rentedCar


person = nil
rentedCar = nil

 

 

 

반응형
저작자표시 비영리 변경금지 (새창열림)

'Swift' 카테고리의 다른 글

Swift | Array capacity, reserveCapacity  (3) 2021.10.20
Swift | 코코아 메모리 관리 모델, ARC  (0) 2021.08.31
Swift | 구조체와 클래스의 차이  (0) 2021.08.31
Swift | 클로저  (0) 2021.08.22
    'Swift' 카테고리의 다른 글
    • Swift | Array capacity, reserveCapacity
    • Swift | 코코아 메모리 관리 모델, ARC
    • Swift | 구조체와 클래스의 차이
    • Swift | 클로저
    ariedaze
    ariedaze

    티스토리툴바