SwiftUI: Navigation Link аварийно завершает работу при повторном нажатии на iOS 14, но не на iOS 13

В настоящее время я работаю над приложением с функцией входа в систему, чтобы опробовать SwiftUI. Сбой происходит как на симуляторе, так и на реальном устройстве. Я могу войти в систему и перейти к следующему экрану. Однако, если я нажму кнопку «Назад» и вернусь к экрану входа в систему, произойдет сбой. Это единственный результат сбоя.

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

Однако при работе на симуляторе iOS 13 сбоев не происходит. Я использую XCode 12.2, и сбой также произошел на 12.1. Вот код.

struct LoginView: View {

    @ObservedObject
    var loginViewModel: LoginViewModel
    
    @State var showSafari = false

    var body: some View {
        NavigationView {
            NavigationLink(destination: MainView(mainViewModel: MainViewModel(Fetcher: Fetcher())), isActive: $loginViewModel.successfulLogin) {
                Button(action: {
                    self.showSafari = true
                }) {
                    Text("Login")
                }
                .sheet(isPresented: $showSafari) {
                    SafariView(handler: loginViewModel.handler)
                }
            }
        }
        .navigationViewStyle(StackNavigationViewStyle())
    }
}
class LoginViewModel: ObservableObject, Identifiable {
    
    private let fetcher: Fetchable
    private var disposables = Set<AnyCancellable>()
    
    @Published
    var successfulLogin: Bool = false
    
    lazy var handler: LoginVCHandler = { [weak self] user, error in
        if let self = self, let user = user, let Id = user.ID {
            self.getPlayerSummary(Id: Id)
        } else {
            print("ERROR: \(error)")
        }
    }
    
    init(Fetcher: Fetchable) {
        self.Fetcher = Fetcher
    }
    
    func getPlayerSummary(Id: String) {
        fetcher.getPlayerSummary(Id: Id)
            .map { response in
                response.response.players
            }
            .receive(on: DispatchQueue.main)
            .sink(receiveCompletion: { value in
                switch value {
                case .failure:
                    print(value)
                    User.shared.cleareUserInfo()
                case .finished:
                  break
                }
            }, receiveValue: { [weak self] players in
                guard let self = self, let player = players.first else { return }
                User.shared.updateUserInfo(username: player.name, firstName: "", lastName: "", Id: Id)
                self.successfulLogin = true
            })
            .store(in: &disposables)
    }
}

Я рассмотрел другие вопросы, например Почему в моем приложении SwiftUI происходит сбой при переходе назад после помещения` NavigationLink` внутри `navigationBarItems` в` NavigationView`? и NavigationLink работает только один раз, в которых говорится, что проблема устранена, но не на основании того, что я вижу.

Вот трассировка стека, когда происходит сбой.

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #0: 0x0000000111c6d63c libsystem_platform.dylib`_os_unfair_lock_recursive_abort + 23
    frame #1: 0x0000000111c68a23 libsystem_platform.dylib`_os_unfair_lock_lock_slow + 256
    frame #2: 0x0000000108cc6f1b Combine`Combine.Publishers.ReceiveOn.(Inner in _1178A6B2012BC46DB46053E713A746B4).cancel() -> () + 27
    frame #3: 0x0000000108cc7c20 Combine`protocol witness for Combine.Cancellable.cancel() -> () in conformance Combine.Publishers.ReceiveOn<A, B>.(Inner in _1178A6B2012BC46DB46053E713A746B4)<A1> : Combine.Cancellable in Combine + 16
    frame #4: 0x0000000108c9234c Combine`Combine.Subscribers.Sink.cancel() -> () + 652
    frame #5: 0x0000000108c92510 Combine`protocol witness for Combine.Cancellable.cancel() -> () in conformance Combine.Subscribers.Sink<A, B> : Combine.Cancellable in Combine + 16
    frame #6: 0x0000000108c7e423 Combine`Combine.AnyCancellable.cancel() -> () + 339
    frame #7: 0x0000000108c7e5f9 Combine`Combine.AnyCancellable.__deallocating_deinit + 9
    frame #8: 0x000000010a676a70 libswiftCore.dylib`_swift_release_dealloc + 16
    frame #9: 0x000000010a66c74b libswiftCore.dylib`swift_arrayDestroy + 59
    frame #10: 0x000000010a4d20fc libswiftCore.dylib`Swift._SetStorage.deinit + 188
    frame #11: 0x000000010a4d2179 libswiftCore.dylib`Swift._SetStorage.__deallocating_deinit + 9
    frame #12: 0x000000010a676a70 libswiftCore.dylib`_swift_release_dealloc + 16
    frame #13: 0x000000010541eb87 GameTracker`outlined destroy of Set<AnyCancellable> at <compiler-generated>:0
    frame #14: 0x000000010542315b GameTracker`MainViewModel.deinit(self=0x0000600003c843f0) at MainViewModel.swift:0
    frame #15: 0x00000001054231b9 GameTracker`MainViewModel.__deallocating_deinit(self=0x0000600003c843f0) at MainViewModel.swift:0
    frame #16: 0x000000010a676a70 libswiftCore.dylib`_swift_release_dealloc + 16
    frame #17: 0x000000010a677519 libswiftCore.dylib`bool swift::RefCounts<swift::SideTableRefCountBits>::doDecrement<(swift::PerformDeinit)1>(unsigned int) + 217
    frame #18: 0x0000000105421545 GameTracker`___lldb_unnamed_symbol12$$GameTracker + 21
    frame #19: 0x000000010a676a70 libswiftCore.dylib`_swift_release_dealloc + 16
    frame #20: 0x0000000108d3c3f8 Combine`Combine.Publishers.FlatMap.(Outer in _E91C3F00A6DFAAFEA2009FAF507AE039).deinit + 120
    frame #21: 0x0000000108d3c459 Combine`Combine.Publishers.FlatMap.(Outer in _E91C3F00A6DFAAFEA2009FAF507AE039).__deallocating_deinit + 9
    frame #22: 0x000000010a676a70 libswiftCore.dylib`_swift_release_dealloc + 16
    frame #23: 0x0000000108c7f2c1 Combine`assignWithTake value witness for Combine.SubscriptionStatus + 49
    frame #24: 0x0000000108c7dc1d Combine`outlined assign with take of Combine.SubscriptionStatus + 29
    frame #25: 0x0000000108cc79cd Combine`closure #1 () -> () in Combine.Publishers.ReceiveOn.(Inner in _1178A6B2012BC46DB46053E713A746B4).receive(completion: Combine.Subscribers.Completion<A.Failure>) -> () + 141
    frame #26: 0x0000000109d4fade libswiftDispatch.dylib`reabstraction thunk helper from @escaping @callee_guaranteed () -> () to @escaping @callee_unowned @convention(block) () -> () + 14
    frame #27: 0x00000001117cc7ec libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #28: 0x00000001117cd9c8 libdispatch.dylib`_dispatch_client_callout + 8
    frame #29: 0x00000001117dbe75 libdispatch.dylib`_dispatch_main_queue_callback_4CF + 1152
    frame #30: 0x000000010b4bddab CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    frame #31: 0x000000010b4b862e CoreFoundation`__CFRunLoopRun + 2685
    frame #32: 0x000000010b4b76c6 CoreFoundation`CFRunLoopRunSpecific + 567
    frame #33: 0x000000010a228db3 GraphicsServices`GSEventRunModal + 139
    frame #34: 0x000000010dee2187 UIKitCore`-[UIApplication _run] + 912
    frame #35: 0x000000010dee7038 UIKitCore`UIApplicationMain + 101
  * frame #36: 0x000000010543058b GameTracker`main at AppDelegate.swift:12:7
    frame #37: 0x000000011185c409 libdyld.dylib`start + 1

person Michael Slattery    schedule 16.11.2020    source источник
comment
Сбой требует отладки, предоставленный код не подлежит тестированию. Как создать минимальный воспроизводимый пример   -  person Asperi    schedule 16.11.2020
comment
Я добавил трассировку стека. Надеюсь, это поможет   -  person Michael Slattery    schedule 16.11.2020


Ответы (1)


На самом деле это было очень простое решение. Просто замените @ObservedObject на @StateObject.

person Michael Slattery    schedule 17.11.2020