SwiftUI:在 iOS 14 上点击返回时导航链接崩溃,但在 iOS 13 上没有
Posted
技术标签:
【中文标题】SwiftUI:在 iOS 14 上点击返回时导航链接崩溃,但在 iOS 13 上没有【英文标题】:SwiftUI: Navigation Link crashes when tapping back on iOS 14 but not on iOS 13 【发布时间】:2021-02-27 15:13:56 【问题描述】:我目前正在开发一个具有登录功能的应用程序来试用 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)
我看过其他问题,例如 Why does my SwiftUI app crash when navigating backwards after placing a `NavigationLink` inside of a `navigationBarItems` in a `NavigationView`? 和 NavigationLink Works Only for Once 表示问题已得到解决,但不是我所看到的。
这是崩溃发生时的堆栈跟踪。
* 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
【问题讨论】:
崩溃需要调试,前提是代码不可测试。 How to create a Minimal, Reproducible Example 我现在添加了一个堆栈跟踪。希望这会有所帮助 【参考方案1】:这实际上是一个非常简单的解决方案。只需将@ObservedObject
替换为@StateObject
。
【讨论】:
以上是关于SwiftUI:在 iOS 14 上点击返回时导航链接崩溃,但在 iOS 13 上没有的主要内容,如果未能解决你的问题,请参考以下文章
Swiftui:当用户点击推送通知时,如何导航到特定的 NavigationLink?
SwiftUI 2.0:如何使用没有标题的工具栏()自定义 iOS 14 导航栏?
iOS 16.2 在 SwiftUI 子视图中无法关闭弹出的(sheet)导航视图(NavigationView)之解决