對於 SwiftUI onDisappear 的誤解?

在接觸 SwiftUI 的這段時間以來,我一直在試著釐清一件事情,那就是

onDisappear 到底是不是壞的!

這件事情很玄,畢竟網路上大部分的資訊都告訴我們 onAppear 類似於 viewDidAppearonDisappear 類似於 ViewDidDisappear,然後再補上一句

Note: In the current SwiftUI beta onDisappear will never be called. by HackingWithSwift

或是你可以看到在 StackOverFlow 上大家是這麼討論的

討論串
討論串

接著,在這一路以來,你又曾經碰過真的是 Apple 的 bug,所以你就會很理所當然地認為⋯⋯

沒錯,onDisappear 就是壞的!

直到認真找找官方文件到底有沒有使用到 onDisappear 的範例,於是找到了這篇 並下載下來研究發現

onDisappear 是會動的⋯

這代表著一件事,就是其實是我誤解它的使用方式,而非它是壞的。 來看看官方的這個 View

struct ProfileHost: View {
    @Environment(\.editMode) var mode
    @State var profile = Profile.default
    @State var draftProfile = Profile.default
    
    var body: some View {
        VStack(alignment: .leading, spacing: 20) {
            HStack {
                if self.mode?.wrappedValue == .active {
                    Button(action: {
                        self.profile = self.draftProfile
                        self.mode?.animation().wrappedValue = .inactive
                    }) {
                        Text("Done")
                    }
                }
				
                Spacer()
				
                EditButton()
            }
            if self.mode?.wrappedValue == .inactive {
                ProfileSummary(profile: profile)
            } else {
                ProfileEditor(profile: $draftProfile)
                    .onDisappear {
                        self.draftProfile = self.profile
                    }
            }
        }
        .padding()
    }
}

想了一下,若是我的話我會將 onDisappear 寫在哪裡?應該會是在 ProfileEditorbody 裡頭吧。而實際上測試了,在 ProfileEditor.body 裡頭實作

.onDisappear { print("disappear") }

是沒有效果的,我才得到一個結論

onDisappear 和 viewDidDisappear 不同

onDisappear 的概念是監聽你底下那個消失的動作

Adds an action to perform when this view disappears.

但並不是像 UIViewController.viewDidDisappear 一樣,是對物件本身消失去做動作。

因為大多數的文章都習慣將 onAppearviewDidAppear 做對比,也就造成我自己對於使用方式上產生誤解;實際上 onDisappear 的動作應該做在 superView 之中,而非直接寫在那個 struct 裡頭。

這大概就是一個從 UIKit 轉到 SwiftUI 才會誤解的地方了⋯⋯如果是一開始就從官方文件開始用 SwiftUI 學習寫 iOS 的人,應該不會陷入這種迷思🤷‍♂️

comments powered by Disqus