다마고치를 키우는 앱을 만들다가 모델을 struct에서 class로 변경하였는데 didSet이 되지 않는 현상이 생김
단지 struct에서 class로 변경한 것 뿐 모든게 동일했는데 왜 안되는 걸까
일단 코드를 살펴보면
struct TamaStruct {
let name = "TAMATAMA"
var rice = 0
var water = 0
}
class TamaClass {
let name = "TAMATAMA"
var rice = 0
var water = 0
}
var tamaStruct = TamaStruct(){
didSet {
print("tamaStruct 변경됨")
}
}
var tamaClass = TamaClass(){
didSet {
print("tamaClass됨 변경됨")
}
}
tamaStruct.rice += 1
tamaClass.rice += 1
tamaClass 인스턴스의 rice와 tamaStruct인스턴스의 rice를 1씩 증가시켰음
여기서 예상한 결과 값은 둘 다 didSet안의 print가 호출되는 거였음
tamaStruct 변경됨
근데 출력은 struct만 됨.. 여기서 class는 didSet이 동작하지 않는건가?라는 일차적인 생각을 하게 됨
tamaClass = TamaClass()
tamaStruct = TamaStruct()
// tamaClass 변경됨
// tamaStruct 변경됨
tamaClass 자체를 바꿔주면 또 동작함. 구조체 인스턴스도 자체를 바꿔주면 동작함
여기서 일단 다른 궁금한 점이 생김
처음 생성할 때도 set되는건데 didSet 왜 안되나요?
didSet은 초기화 이후에만 불림. 그렇기 때문에 처음에 만들어도 호출되지 않고 그 이후 뭔가 값이 변동되면 호출됨
다시 돌아가서 class의 경우 왜 안되는지 생각해보도록 함
class는 참조타입이고 힙에 저장됨
이 참조타입의 인스턴스는 객체 원본의 주소값만 알고 있고 그 외의 정보는 모름
그렇다면 TamaClass의 rice가 변경되더라도 인스턴스는 해당정보를 알 수가 없고
TamaClass 자체에 변화가 있어야 동작함
struct는 값타입이고 스택에 저장됨
이 값타입의 인스턴스는 그 객체 자체의 정보를 갖고 있음. tamaStruct는 TamaStruct의 모든 정보를 갖고 있는 것임
그렇기 때문에 변화를 감지할 수 있음
또 참조타입은 제자리에서 변할 수 없어서 변수의 변경이 곧 인스턴스의 변경이 됨
그렇기 때문에 tamaStruct 자체에 didSet이 되어있어도 변수가 변경될 때 변화를 감지할 수 있음
요약
1. Class 인스턴스는 원본의 주소값만 가지고 있기 때문에 인스턴스 재생성과 같은 자체의 변화가 있어야 didSet이 동작
2. Struct 인스턴스는 변수의 변경이 곧 인스턴스의 변경이 됨(전체 복사의 개념)
'iOS > 쫌쫌따리 트러블슈팅' 카테고리의 다른 글
[iOS] StackView를 사용한 채팅 UI 구현 (1) | 2024.11.28 |
---|