일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- 풀이
- 백준
- 프로그래머스
- 해시
- rx
- 구조체
- 자바
- 프래그먼트
- noncopyable
- 클로저
- 알고리즘
- 연산자
- RxSwift
- weak
- 리스트뷰
- View
- 옵셔널
- 차이
- concurrency
- observable
- Subject
- 프로퍼티
- async
- ios
- 이스케이핑
- Swift
- 생명주기
- 스위프트
- 안드로이드
- Self
- Today
- Total
study record
[Swift] Struct 내 Class 프로퍼티는 복사될까? isKnownUniquelyReferenced? 본문
Struct 내 Class 프로퍼티는 복사될까?
Struct는 값 타입으로 값을 복사한다.
그렇다면 Struct 내의 Class 프로퍼티는 복사될까 아니면 참조 주소 값을 공유하게 될까?
정답은 Struct 내의 Class 프로퍼티는 참조 주소 값을 공유한다.
이에 다음과 같은 문제가 발생할 수 있다.
📌 "Struct의 class 프로퍼티에서 생길 수 있는 문제?
1. 문제 개요
Swift에서 struct(값 타입) 내에 클래스(참조 타입) 프로퍼티를 포함할 때, 참조 타입이므로 원본이 공유될 수 있는 문제가 있다.
특히 클래스가 상속(subclassing) 될 수 있는 경우, 원치 않는 변경이 발생할 수 있다.
2. 어떤 문제가 발생할 수 있나?
만약 struct 내에 참조 타입인 클래스 프로퍼티가 있고, 여러 변수가 해당 struct를 공유하면 한 곳에서 클래스의 속성을 변경하면 다른 곳에서도 변경이 반영된다.
이것은 struct의 값 타입(Value Type) 특성과 맞지 않으며, 예기치 않은 버그를 유발할 수 있다.
📌 isKnownUniquelyReferenced를 사용하여 해결
위 문제를 해결하려면 struct가 복사될 때 내부 참조 타입이 공유되지 않도록 보장해야 한다.
이를 위해 isKnownUniquelyReferenced(_:)를 활용하면 된다.
isKnownUniquelyReferenced(_:)란?
- 참조 타입이 현재 유일하게 참조되고 있는지 확인하는 함수.
- true이면, 해당 객체가 유일하게 참조됨(즉, 안전하게 변경 가능).
- false이면, 해당 객체가 여러 곳에서 공유됨(즉, 변경 전 복사 필요).
struct Material {
public var roughness: Float
public var color: Color
private var _texture: Texture
// ✅ 프로퍼티 감시자에서 `isKnownUniquelyReferenced` 사용
public var isSparkly: Bool {
get { _texture.isSparkly }
set {
if !isKnownUniquelyReferenced(&_texture) {
_texture = Texture(copying: _texture) // ✅ 복사본 생성하여 변경
}
_texture.isSparkly = newValue
}
}
}
위 코드에서 Texture(copying: _texture)라는 초기화 메서드는 Swift의 내장 기능이 아니라, 사용자가 직접 구현해야 하는 생성자이다.
Swift의 클래스는 기본적으로 복사 생성자(Copy Constructor)를 제공하지 않으므로, 명시적으로 "복사 생성자"를 만들어야 한다.
class Texture {
var isSparkly: Bool
// 기본 생성자
init(isSparkly: Bool) {
self.isSparkly = isSparkly
}
// ✅ 복사 생성자 (Copy Initializer)
init(copying texture: Texture) {
self.isSparkly = texture.isSparkly
}
}
📌 ✅ copying 생성자 없이 NSCopying을 활용하는 방법
만약 Swift의 프로토콜 기반 복사를 원한다면, NSCopying을 채택하는 방법도 있다.
class Texture: NSCopying {
var isSparkly: Bool
init(isSparkly: Bool) {
self.isSparkly = isSparkly
}
// ✅ NSCopying 프로토콜 구현
func copy(with zone: NSZone? = nil) -> Any {
return Texture(isSparkly: self.isSparkly)
}
}
_texture = _texture.copy() as! Texture
참고
'Swift > 스위프트 정리' 카테고리의 다른 글
[Swift] DispatchSemaphore - Swift에서 세마포어 사용하기! (0) | 2024.05.28 |
---|---|
[Swift] Creating and Managing Dispatch Queues (0) | 2023.02.13 |
[Swift] Dispatch Queues (0) | 2023.02.07 |
[Swift] Swift 고차함수(map 시리즈, reduce, filter) (0) | 2023.01.30 |
[Swift] Combine 연산자와 CheckedContinuation (0) | 2023.01.29 |