티스토리 뷰
combine과 observableobject를 사용하여 간단하게 구현해 보고 비교해보려 한다.
2024.03.15 - [Swift] - [swift] Combine & ObservableObject
[swift] Combine & ObservableObject
오늘은 swiftUI에서 꼭 알아야 하는 Combine랑 ObservableObject에 대해 차이점과 각 특징들을 비교해보자! Combine 공식문서를 찾아보면 combine은 비동기 작업과 이벤트 처리를 사용자 정의한다고 작성되어
yanni13.tistory.com
이전 포스팅에서 같이 개념을 설명하면서 예제까지 작성하려 했으나 생각보다 길어질 거 같아서 글을 나누었다.
대충 2편이라고 생각해주면 될 듯!
예제
Combine
import Combine
import SwiftUI
struct ContentView: View {
var vm = CombineViewModel()
@State var anyCancellable = Set<AnyCancellable>()
@State var number = 0
var body: some View {
VStack {
Text("John Appleseed, Age: \(number)")
.padding()
Button(action: {
vm.number.value += 1
//print(vm.number.value)
}, label: {
Text("Celebrate Birthday")
})
.onAppear {
vm.number.sink { [self] value in
DispatchQueue.main.async {
self.number = value
}
}.store(in: &anyCancellable)
}
}
}
}
위 코드는 애플 공식문서에서 올려놓은 코드를 참고하여 가공했다.
코드를 하나하나 뜯어보자!!!!!
view랑 viewmodel를 따로 구분해서 파일을 만들었다.
CombineViewModel
import Combine
import SwiftUI
class CombineViewModel {
var number = CurrentValueSubject<Int, Never>(23)
//하나의 값을 둘러싸고 값이 변동될 때 publish
}
코드에 대한 전반적인 설명은 celebrate birthday 버튼을 누르면 john의 나이가 증가한다. (내 나이는 아니길 바람 ㅎ)
공식문서에 올려놓은 코드를 봤을 때 나는 combine으로 구현하려 했는데 무슨 AnyCancellable에다가.. sink에다가.. 이게 뭔데?? 했었다
차근차근 파헤쳐 보자.
AnyCancellable
combine 프레임워크에서 발생하는 구독을 취소하거나 처리하는 데 사용되는 타입이다.
combine에서 subscriber에게 값을 전달하는 동안 구독이 취소되거나 완료되면 해당 구독을 메모리에서 해제해야 하기 때문에 그때 쓰이는게 AnyCancellable이다.
메모리 누수를 방지하니 메모리 관점에서 좋을거 같다.
@State var anyCancellable = Set<AnyCancellable>()
AnyCancellable을 저장하는 set타입을 변수로 지정해 뷰가 해제될 때 구독을 취소할 수 있도록 선언해 주었다.
.store(in: &anyCancellable)을 통해 구독을 저장하여 뷰가 해제될 때 해당 구독을 취소할 수 있다.
sink
sink의 반환값도 AnyCancellable임을 확인할 수 있다.
공식문서를 보면.. 절대 실패하지 않는 publisher에 폐쇄 기반을 가진 subscriber를 첨부한다고 한다
이해하기 쉽게 설명해 보자면, publisher의 값을 처리하는 역할을 하며 publisher가 subscriber에게 값을 전달할 때 사용된다.
vm.number.sink { [self] value in
DispatchQueue.main.async {
self.number = value
}
위의 코드에서 sink메서드를 사용하여 vm의 number를 구독하고 값의 변경사항을 감지하여 UI를 업데이트하도록 한다.
ObservableObject
import SwiftUI
import Combine
class Contact: ObservableObject {
@Published var name: String
@Published var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func haveBirthday() -> Int {
age += 1
return age
}
}
struct ObserableObject: View {
@StateObject private var john = Contact(name: "John Appleseed", age: 23)
var body: some View {
VStack {
Text("\(john.name), Age: \(john.age)")
.padding()
Button("Celebrate Birthday") {
let newAge = john.haveBirthday()
print("New age is \(newAge)")
}
}
.onAppear {
let cancellable = john.objectWillChange.sink { _ in
print("\(john.age) will change")
}
}
}
}
위와 똑같은 UI와 기능도 똑같은데 코드는 다른 게 신기하지 않나요????
아무튼.. 이 코드들도 파헤쳐보자.
combine을 사용한 observableobject를 구현한 예시이다.
name과 age를 @publisher 속성을 채택해 속성의 변경사항을 swiftUI에 알리는 역할을 한다.
StateObject
관찰 가능한 객체를 인스턴스화하는 propertyWrapper라고 한다.
StateObject까지 설명하면 포스팅하려고 했던 주제에서 벗어나게 되는 거 같아서 이 부분은 ObservedObject와 함께 작성하도록 하겠다.
뷰의 상태를 관리하고 추적한다고만 일단 알고 넘어가자!
@StateObject private var john = Contact(name: "John Appleseed", age: 23)
위 코드에서는 해당 뷰의 상태를 관리하는 속성이며 contect 클래스의 인스턴스를 생성하여 john에게 저장된다는 정도로만 이해해 보자
ObjectWillchange
객체가 변경되기 전에 내보내는 publisher라고 한다.
objectWillChange는 ObservableObject 프로토콜의 일부이며 이 프로토콜로 구현한 객체는 내부의 데이터가 바뀔 때마다 publisher를 통해 변경사항을 swiftUI에 알릴 수 있다.
let cancellable = john.objectWillChange.sink { _ in
print("\(john.age) will change")
}
위의 코드에서는 objectWillChange에 대한 sink를 설정하여 john의 상태가 변경될 때마다 호출되며 나이가 변경된다.
느낀 점
여전히 스유에 대해서 이해하는 건 어렵지만.. 확실히 블로그에 정리하고 코드를 하나하나 뜯어보면서 적용시켜 보니 그냥 애플 공식문서를 읽고 WWDC 강의만 봤을 때 보다 훨씬 이해가 잘 되긴 한다.
이제 0.1 걸음 정도.. 나아갔다고 할 수 있으려나 하하하하
뭐든 꾸준히 해보자~!~!~! 아좌좌..
'iOS > Swift' 카테고리의 다른 글
[iOS] lazy var에 대해 알아보기 (0) | 2024.09.21 |
---|---|
[iOS/Swift] Closure (0) | 2024.05.08 |
[swiftUI] NSPredicate (0) | 2024.03.30 |
[Swift] Optional (1) | 2024.03.28 |
[Swift] map 함수 정리하기 (0) | 2024.02.27 |
- Total
- Today
- Yesterday
- group tasks
- 16173
- detached task
- 코딩테스트
- mergeconflict
- 스위프트
- swiftUI
- ObservableObject
- XCTest
- mlmodel
- 병합충돌
- Fastlane
- closure
- 클로저
- SWIFT
- imagepicker
- 프로그래머스
- asyne-let
- Xcode
- foundation models
- ios
- UIKit
- 백준
- rxswift
- securefield
- Task
- combine
- unstructed task
- CoreData
- wwdc25
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |