class OnReceiveClass: ObservableObject {
@Published var data: [String] = [] // View는 @Published속성이 언제 변경되는지 알고싶어한다.
func fetchData() {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 3) { [self] in
data = ["Datum 1", "Datum 2", "Datum 3"]
}
}
}
struct OnReceive: View {
@StateObject var onRecevieClass = OnReceiveClass()
@State private var isProcessing = true
var body: some View {
VStack(spacing: 20) {
CommonTextView(title: "onReceive", desc: "관찰된(Observe) 객체의 게시자(Publisher)가 값을 변경할 때 코드를 실행하려면 onReceive 사용")
ZStack {
List(onRecevieClass.data, id: \.self) { datum in
Text(datum)
}
if isProcessing {
ProgressView()
}
}
}
.onAppear {
onRecevieClass.fetchData()
}
.onReceive(onRecevieClass.$data) { _ in // $의 위치 주목. $는 속성의 게시자(Publisher)를 보여줌.
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
isProcessing = false
}
}
}
}
class OnReceiveClass: ObservableObject {
@Published var name = "June"
}
struct OnReceivePublisherOutput: View {
@StateObject var onReceiveClass = OnReceiveClass()
@State private var originValue = "June"
@State private var nameText = ""
@State private var disabled = true
var body: some View {
VStack(spacing: 20) {
CommonTextView(title: "onReceive", desc: "onReceive의 클로저 매개변수로, Publisher가 보낸 데이터 검사함")
TextField("이름 입력", text: $onReceiveClass.name)
.textFieldStyle(.roundedBorder)
.padding()
Button("저장하기") {
originValue = onReceiveClass.name
}
.disabled(disabled) // 데이터가 변경된 경우에만 저장 버튼 활성화
.onReceive(onReceiveClass.$name) { newValue in
disabled = (newValue == originValue) // 클로저에서 매개변수로 받은 새 값(newValue)를 검사할 수 있음.
}
}
}
}
OnReceiveClass 내부에서 Publish중인 name 속성의 변화를 감지해, name 속성이 직전의 값과 차이가 있는 경우에만 '저장하기' 버튼이 활성화되는 코드.
class UserModel: ObservableObject {
@Published var username = "June"
// showAsOnline 속성의 변경 사항 추적중.
// 변경된 경우 값을 비교해 UI에 다시 연결하는 옵션을 표시함.
@Published var showAsOnline = true
}
struct onReceiveWithEnvironmentObject: View {
@EnvironmentObject var user: UserModel
@State private var reconnect = false
var body: some View {
VStack(spacing: 15) {
CommonTextView(title: "onReceive", desc: "onReceive를 사용해 global environment object(전역 환경 객체) 변경에도 대응")
Button(reconnect ? "" : "연결 끊기") { user.showAsOnline = false }
Spacer()
if reconnect {
HStack {
Text("연결 끊어짐")
.frame(maxWidth: .infinity, alignment: .leading)
Button {
user.showAsOnline = true
} label: {
Text("연결하기")
}
.buttonStyle(.borderedProminent)
}
.padding()
.background(Color.red)
}
}
.onReceive(user.$showAsOnline) { online in
if online == false {
reconnect = true
} else {
reconnect = false
}
}
}
}