OnAppear неожиданно вызывает, когда клавиатура появляется в SwiftUI

Я наблюдаю очень странное поведение в SwiftUI 2.0 и iOS14.

Когда на экране появляется клавиатура, автоматически вызывается метод OnAppear представления другой вкладки.

Однако это отлично работает Xcode 11.7

Вот проблема в действии. «Текстовое

Вот код, который вызывает указанную выше ошибку.

struct ContentView: View {
    var body: some View {
        TabView {
            DemoView(screenName: "Home")
                .tabItem {
                    Image.init(systemName: "star.fill")
                    Text("Home")
                }
            DemoView(screenName: "Result")
                .tabItem {
                    Image.init(systemName: "star.fill")
                    Text("Result")
                }
            DemoView(screenName: "More")
                .tabItem {
                    Image.init(systemName: "star.fill")
                    Text("More")
                }
        }
    }
}

struct DemoView:View {
    
    @State var text:String = ""
    var screenName:String
    var body: some View {
        VStack{
            Text(screenName)
                .font(.title)
            
            TextField("Buggy Keyboard Issue", text: $text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
                
            Text("Issue : When keyboard appears, onAppear of other 2 tabs call automatically.")
                .font(.footnote)
        }
        .padding()
        .onAppear(perform: {
            debugPrint("OnAppear of : \(screenName)")
        })
    }
}

Кажется, это ошибка SwiftUI 2.0, но я не уверен. Любая помощь будет оценена по достоинству.

Спасибо


person Malav Soni    schedule 23.09.2020    source источник
comment
Я уже сообщил Apple об этом поведении. feedbackassistant.apple.com/feedback/8732425   -  person Malav Soni    schedule 23.09.2020
comment
SwiftUI onAppear не равен UIKit viewDidAppear. Они вызывают onAppear, как только представление становится визуализированным в иерархии представлений (а не тогда, когда оно становится видимым для пользователя). Когда, почему и сколько раз он вызывается - это совершенно другой вопрос, и на самом деле он нигде не указан / не задокументирован, поэтому я бы просто не полагался на это поведение, потому что оно меняется от версии к версии.   -  person Asperi    schedule 23.09.2020
comment
Неа. Вы испытали то же самое?   -  person Malav Soni    schedule 02.10.2020
comment
Да :/ .   -  person Hüseyin    schedule 04.10.2020
comment
Та же проблема для меня !. Если мы не можем полагаться на onAppear, где мы должны делать сетевые вызовы, когда вид виден.   -  person Armin    schedule 16.10.2020


Ответы (3)


У меня такая же проблема, я думаю, что это ошибка или что-то в этом роде, однако я придумал решение, возможно, обходной путь, пока Apple не исправит его.

То, что я сделал, в основном я использовал LazyVStack, и, похоже, он работает отлично.

LazyVStack {
    VStack{
        Text(screenName)
            .font(.title)
        
        TextField("Buggy Keyboard Issue", text: $text)
            .textFieldStyle(RoundedBorderTextFieldStyle())
            
        Text("Issue : When keyboard appears, onAppear of other 2 tabs call automatically.")
            .font(.footnote)
    }
    .padding()
    .onAppear(perform: {
        debugPrint("OnAppear of : \(screenName)")
})
}

Теперь OnAppear метод просмотра другой вкладки не вызывается автоматически при появлении клавиатуры.

Решение

person Cod3rMax    schedule 11.12.2020
comment
что здесь делает lazyvstack? - person bze12; 03.01.2021
comment
это сработало для меня. Я думаю, что другие виды вкладок перезагружаются, когда появляется клавиатура. lazyvstack заставляет представление не перезагружаться, когда клавиатура появляется на другой вкладке. - person Falco Winkler; 14.02.2021

Чтобы избежать перезагрузки вашего представления, попробуйте на TabView

.ignoresSafeArea(.keyboard, edges: .bottom)

Работает только на iOS 14

person Alfonso Mestre    schedule 21.10.2020
comment
У меня это не сработало, реализация показана в щедрости - person 1dolinski; 22.10.2020
comment
У меня тоже не работает - person AsMartynas; 25.01.2021
comment
это не сработает, это ошибка в SwiftUI. Я отправил отзыв в Apple, но еще не получил ответа: FB8646389, на самом деле эта ошибка вызывает множество неожиданных поведений в моем коде - person JAHelia; 31.03.2021

Только что реализовал следующий обходной путь:

struct ContentView: View {
    var body: some View {
        TabView(selection: $selectedTab) {
            TabContentView(tag: 0, selectedTag: selectedTab) {
                Text("Some tab content")
            }
            .tabItem {
                Text("First tab")
            }
            TabContentView(tag: 0, selectedTag: selectedTab) {
                Text("Another tab content")
            }
            .tabItem {
                Text("Second tab")
            }
        }
    }
    
    @State private var selectedTab: Int = 0
}

private struct TabContentView<Content: View, Tag: Hashable>: View {
    init(tag: Tag, selectedTag: Tag, @ViewBuilder content: @escaping () -> Content) {
        self.tag = tag
        self.selectedTag = selectedTag
        self.content = content
    }

    var body: some View {
        Group {
            if tag == selectedTag {
                content()
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            } else {
                Color.clear
            }
        }
        .tag(tag)
    }

    private let tag: Tag
    private let selectedTag: Tag
    private let content: () -> Content
}

Не уверен, что он достаточно стабилен, но внешний вид клавиатуры больше не запускает onAppear содержимое вкладок.

person Mark Kotevode    schedule 27.04.2021