记录各种疑难杂症
1. Terminating app due to uncaught exception 'UIApplicationInvalidInterfaceOrientation', reason: 'Supported orientations has no common orientation with the application, and [UIAlertController shouldAutorotate] is returning YES'
由于APP只支持竖屏,而在其中某个页面中单独设置支持横屏,在此横屏页面下,如果触发了某个业务弹出了UIAlertController
,则会导致崩溃。网上有说写一个UIAlertController
分类,在其中重写shouldAutorotate
方法处理,然而写了之后并不会执行。
当然不仅仅是UIAlertController
这一种情况,UIImagePickerViewController
这种系统的东西都有可能触发。
解决方案:在AppDelegate
中实现以下方法根据实际业务判断处理
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
UIViewController *rootVC = window.rootViewController;
if (rootVC.presentedViewController) {
UIViewController *theVC = rootVC.presentedViewController;
while (theVC.presentedViewController) {
theVC = theVC.presentedViewController;
}
if ([theVC shouldAutorotate]) {
return UIInterfaceOrientationMaskAll;
}
return theVC.supportedInterfaceOrientations;
}
return rootVC.supportedInterfaceOrientations;
}
2. iOS 16实时活动API,在iPhone上没问题,在M1上打开闪退。
闪退堆栈
* thread #26, queue = 'com.apple.root.user-initiated-qos.cooperative', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
* frame #0: 0x00000001a37e442c libswiftCore.dylib`swift::ResolveAsSymbolicReference::operator()(swift::Demangle::__runtime::SymbolicReferenceKind, swift::Demangle::__runtime::Directness, int, void const*) + 176
frame #1: 0x00000001a380ee3c libswiftCore.dylib`swift::Demangle::__runtime::Demangler::demangleSymbolicReference(unsigned char) + 228
frame #2: 0x00000001a380b1cc libswiftCore.dylib`swift::Demangle::__runtime::Demangler::demangleType(__swift::__runtime::llvm::StringRef, std::__1::function<swift::Demangle::__runtime::Node* (swift::Demangle::__runtime::SymbolicReferenceKind, swift::Demangle::__runtime::Directness, int, void const*)>) + 264
frame #3: 0x00000001a37ec3e4 libswiftCore.dylib`swift_getTypeByMangledNameImpl(swift::MetadataRequest, __swift::__runtime::llvm::StringRef, void const* const*, std::__1::function<swift::TargetMetadata<swift::InProcess> const* (unsigned int, unsigned int)>, std::__1::function<swift::TargetWitnessTable<swift::InProcess> const* (swift::TargetMetadata<swift::InProcess> const*, unsigned int)>) + 504
frame #4: 0x00000001a37e7a3c libswiftCore.dylib`swift_getTypeByMangledName + 832
frame #5: 0x00000001a37e7d4c libswiftCore.dylib`swift_getTypeByMangledNameInContext + 164
frame #6: 0x0000000103d2b1c4 XXXX`__swift_instantiateConcreteTypeFromMangledName at <compiler-generated>:0
frame #7: 0x0000000103d2b408 XXXX`partial apply for closure #1 in static Bridge.stop(_:) at <compiler-generated>:0
frame #8: 0x0000000103d2b784 XXXX`thunk for @escaping @callee_guaranteed @Sendable @async () -> (@out A) at <compiler-generated>:0
frame #9: 0x0000000103d2c1ac XXXX`partial apply for thunk for @escaping @callee_guaranteed @Sendable @async () -> (@out A) at <compiler-generated>:0
定位代码
Activity<WidgetAttributes>.activities
只要写了这个API
,即便是不做其他事情,也会闪退,最终只能判断在iPad
上不调用。
一开始无法定位,bugly
上只有__swift_instantiateConcreteTypeFromMangledName
,通过这个搜索到的都是说OC与Swift
类型转换的问题,完全误导了排查方向。
3. dyld[41865]: Symbol not found: OBJC_CLASS$_Reachability
OC
项目中使用到了Swift
库,此库依赖了ReachabilitySwift
库。同时之前也存在了Reachability
的OC
版本库,编译时是两个名字的库未发生问题,运行时由于有相同类名导致找不到对应路径。只需要删除其中一个库便可。
4. DYLD, Library not loaded
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note: EXC_CORPSE_NOTIFY
Termination Description: DYLD, Library not loaded: /System/Library/Frameworks/SwiftUI.framework/SwiftUI | Referenced from: /var/containers/Bundle/Application/D24B9375-7B33-4578-A87F-69A052688796/XXX.app/XXX | Reason: image not found
Triggered by Thread: 0
这个问题发生的场景是Xcode 15
打包,在iOS 13(不含)
之前系统无法启动APP
。由于提示原因是SwiftUI.framework
找不到,而且项目确实引用了这个库,就针对引用的项目都做了适配。奇怪的是后来没有引用这个库的APP
也无法打开,为了研究这个原因,新建项目测试,最终发现OC
主项目中只要包含了一个Swift
文件,那么编译的包就会包含一堆Swift
库。
/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony (compatibility version 1.0.0, current version 0.0.0)
/System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 2202.0.0)
/System/Library/Frameworks/UIKit.framework/UIKit (compatibility version 1.0.0, current version 7209.1.102)
@rpath/YBKit.framework/YBKit (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1336.62.1)
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 2202.0.0)
/System/Library/Frameworks/SwiftUI.framework/SwiftUI (compatibility version 1.0.0, current version 5.2.12)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1600.157.0)
/usr/lib/swift/libswiftCore.dylib (compatibility version 1.0.0, current version 5.9.2)
/usr/lib/swift/libswiftCoreFoundation.dylib (compatibility version 1.0.0, current version 120.100.0, weak)
/usr/lib/swift/libswiftCoreImage.dylib (compatibility version 1.0.0, current version 2.0.0, weak)
/usr/lib/swift/libswiftDarwin.dylib (compatibility version 1.0.0, current version 0.0.0, weak)
/usr/lib/swift/libswiftDataDetection.dylib (compatibility version 1.0.0, current version 757.6.0, weak)
/usr/lib/swift/libswiftDispatch.dylib (compatibility version 1.0.0, current version 34.0.2, weak)
/usr/lib/swift/libswiftFileProvider.dylib (compatibility version 1.0.0, current version 1703.62.4, weak)
/usr/lib/swift/libswiftMetal.dylib (compatibility version 1.0.0, current version 341.35.0, weak)
/usr/lib/swift/libswiftOSLog.dylib (compatibility version 1.0.0, current version 4.0.0, weak)
/usr/lib/swift/libswiftObjectiveC.dylib (compatibility version 1.0.0, current version 8.0.0)
/usr/lib/swift/libswiftQuartzCore.dylib (compatibility version 1.0.0, current version 3.0.0, weak)
/usr/lib/swift/libswiftUniformTypeIdentifiers.dylib (compatibility version 1.0.0, current version 794.2.2, weak)
/usr/lib/swift/libswiftos.dylib (compatibility version 1.0.0, current version 1040.0.0, weak)
/usr/lib/swift/libswiftFoundation.dylib (compatibility version 1.0.0, current version 1.0.0, weak)
/usr/lib/swift/libswiftUIKit.dylib (compatibility version 1.0.0, current version 1.0.0, weak)
/usr/lib/swift/libswiftCoreGraphics.dylib (compatibility version 1.0.0, current version 120.100.0, weak)
解决方法有两种:
1. Other Linker Flags下面添加两行
-weak_framework
"SwiftUI"
2. Link Binary With Libraries 中添加对应的 framework
在 Status 中选择为 Optional
个人倾向于第一种方案,因为第二种方案项目中确实没有使用这个库。
5. OC与Swift混编闪退情况
① Swift.*._unconditionallyBridgeFromObjectiveC
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00000001e5236198 libsystem_kernel.dylib`__pthread_kill + 8
frame #1: 0x00000001f47c15f8 libsystem_pthread.dylib`pthread_kill + 208
frame #2: 0x00000001b08804b8 libsystem_c.dylib`abort + 124
frame #3: 0x00000001a3bd8998 libswiftCore.dylib`swift::fatalErrorv(unsigned int, char const*, char*) + 132
frame #4: 0x00000001a3bd89b4 libswiftCore.dylib`swift::fatalError(unsigned int, char const*, ...) + 28
frame #5: 0x00000001a3bd06ec libswiftCore.dylib`swift::swift_dynamicCastFailure(void const*, char const*, void const*, char const*, char const*) + 76
frame #6: 0x00000001a3bd0764 libswiftCore.dylib`swift::swift_dynamicCastFailure(swift::TargetMetadata<swift::InProcess> const*, swift::TargetMetadata<swift::InProcess> const*, char const*) + 120
frame #7: 0x00000001a3bd46ac libswiftCore.dylib`swift_dynamicCast + 280
frame #8: 0x00000001a3f56b18 Foundation`generic partial specialization <Signature = @escaping @convention(thin) <τ_0_0, τ_0_1 where τ_0_0 == Swift.AnyObject> (@guaranteed Swift.Array<Swift.AnyObject>) -> (@owned Swift.Array<τ_0_1>)> of Swift._arrayForceCast<τ_0_0, τ_0_1>(Swift.Array<τ_0_0>) -> Swift.Array<τ_0_1> + 336
frame #9: 0x00000001a3f87d50 Foundation`static Swift.Array._unconditionallyBridgeFromObjectiveC(Swift.Optional<__C.NSArray>) -> Swift.Array<τ_0_0> + 260
frame #10: 0x00000001002b95e0 TestBugly`@objc static Test.array(_:) at <compiler-generated>:0
* frame #11: 0x00000001002b82a8 TestBugly`-[ViewController crash:](self=0x0000000129f0c620, _cmd="crash:", sender=0x0000000129e0f2b0) at ViewController.m:102:5
此情况是由于OC调用Swift方法传入参数为nil或集合类内部元素类型不匹配
Example:
func url(_ url: URL) {}
[Test url:nil];
func array(_ array: [String]) {}
[Test array:@[@1]];
6. UICollectionViewDiffableDataSource闪退
UITableView、UICollectionView
在iOS 13
有了新的布局和刷新方式,之前一直没用过,也不知道会有什么坑,从Bugly
上看到了一个闪退问题多次上报,上报原因是数组越界,从代码层面分析半天也没分析出来。后来统计了上报的机型,发现都是iOS 13
的系统,于是就拿出了我压箱底的6SP
,一运行果然闪退了。
// 崩溃行
self.diffableDataSource?.apply(snapshot);
// 堆栈
Thread 1: "*** -[__NSArrayM objectAtIndexedSubscript:]: index 1 beyond bounds for empty array"
* thread #1, queue = 'com.apple.uikit.datasource.diffing', stop reason = hit Objective-C exception
frame #0: 0x00000001a9f12b94 libobjc.A.dylib`objc_exception_throw
frame #1: 0x00000001aa246280 CoreFoundation`_CFThrowFormattedException + 112
frame #2: 0x00000001aa0db72c CoreFoundation`-[__NSArrayM objectAtIndexedSubscript:] + 180
frame #3: 0x00000001ada70bc0 UIKitCore`-[_UICollectionCompositionalLayoutSolver _computeInitialSupplementaryKeysSectionDictForUpdate:] + 676
frame #4: 0x00000001ada674ac UIKitCore`-[_UICollectionCompositionalLayoutSolver resolveSolutionForUpdate:] + 212
frame #5: 0x00000001ada5fea4 UIKitCore`-[UICollectionViewCompositionalLayout _updateResolve] + 260
frame #6: 0x00000001ada5e2d4 UIKitCore`-[UICollectionViewCompositionalLayout invalidateLayoutWithContext:] + 604
frame #7: 0x00000001adb2a8d4 UIKitCore`-[UICollectionViewLayout _invalidateLayoutUsingContext:] + 60
frame #8: 0x00000001adaf6a24 UIKitCore`-[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:] + 10304
frame #9: 0x00000001adafedb8 UIKitCore`-[UICollectionView _endUpdatesWithInvalidationContext:tentativelyForReordering:animator:] + 92
frame #10: 0x00000001adaff104 UIKitCore`-[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:] + 408
frame #11: 0x00000001adafef4c UIKitCore`-[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:] + 96
frame #12: 0x00000001adafeed0 UIKitCore`-[UICollectionView _performBatchUpdates:completion:invalidationContext:] + 84
frame #13: 0x00000001adafee0c UIKitCore`-[UICollectionView performBatchUpdates:completion:] + 64
frame #14: 0x00000001adb0cb84 UIKitCore`-[UICollectionView _performDiffableUpdate:] + 48
frame #15: 0x00000001adab501c UIKitCore`-[_UIDiffableDataSourceViewUpdater _performUpdateWithCollectionViewUpdateItems:dataSourceSnapshotter:updateHandler:completion:] + 448
frame #16: 0x00000001adaae5b0 UIKitCore`-[__UIDiffableDataSource _commitNewDataSource:withViewUpdates:completion:] + 288
frame #17: 0x00000001adaa9640 UIKitCore`__66-[__UIDiffableDataSource applyDifferencesFromSnapshot:completion:]_block_invoke.154 + 176
frame #18: 0x00000001adaa98e4 UIKitCore`__66-[__UIDiffableDataSource applyDifferencesFromSnapshot:completion:]_block_invoke.180 + 124
frame #19: 0x0000000107887730 libdispatch.dylib`_dispatch_client_callout + 16
frame #20: 0x0000000107896488 libdispatch.dylib`_dispatch_lane_barrier_sync_invoke_and_complete + 124
frame #21: 0x00000001adaa913c UIKitCore`-[__UIDiffableDataSource applyDifferencesFromSnapshot:completion:] + 896
frame #22: 0x00000001adaaa194 UIKitCore`-[__UIDiffableDataSource applyDifferencesFromSnapshot:animatingDifferences:completion:] + 84
frame #23: 0x00000001e04072f4 libswiftUIKit.dylib`merged UIKit.UICollectionViewDiffableDataSource.apply(_: UIKit.NSDiffableDataSourceSnapshot<τ_0_0, τ_0_1>, animatingDifferences: Swift.Bool, completion: Swift.Optional<() -> ()>) -> () + 216
按照给出的数组越界去查找原因,实在是没找出问题。然后发现有些页面调用此API
没有闪退,对比发现是因为animatingDifferences
属性设置为了false
,鉴于此,就加上这个试一下,哦吼,闪退解决了嘿。
如果修改每个调用地方的话太麻烦了,直接使用扩展解决
extension UICollectionViewDiffableDataSource {
func apply(_ snapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>, animatingDifferences: Bool = true) {
var animate = animatingDifferences;
if #available(iOS 14.0, *) {}
else {
animate = false;
}
self.apply(snapshot, animatingDifferences: animate, completion: nil)
}
}