記錄各種疑難雜癥
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只支持豎屏,而在其中某個頁面中單獨設(shè)置支持橫屏,在此橫屏頁面下,如果觸發(fā)了某個業(yè)務(wù)彈出了UIAlertController
缴守,則會導(dǎo)致崩潰。網(wǎng)上有說寫一個UIAlertController
分類暂刘,在其中重寫shouldAutorotate
方法處理牍蜂,然而寫了之后并不會執(zhí)行。
當(dāng)然不僅僅是UIAlertController
這一種情況菩掏,UIImagePickerViewController
這種系統(tǒng)的東西都有可能觸發(fā)。
解決方案:在AppDelegate
中實現(xiàn)以下方法根據(jù)實際業(yè)務(wù)判斷處理
- (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
上不調(diào)用。
一開始無法定位迹恐,bugly
上只有__swift_instantiateConcreteTypeFromMangledName
挣惰,通過這個搜索到的都是說OC與Swift
類型轉(zhuǎn)換的問題,完全誤導(dǎo)了排查方向殴边。
3. dyld[41865]: Symbol not found: OBJC_CLASS$_Reachability
OC
項目中使用到了Swift
庫憎茂,此庫依賴了ReachabilitySwift
庫。同時之前也存在了Reachability
的OC
版本庫锤岸,編譯時是兩個名字的庫未發(fā)生問題竖幔,運行時由于有相同類名導(dǎo)致找不到對應(yīng)路徑。只需要刪除其中一個庫便可是偷。
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
這個問題發(fā)生的場景是Xcode 15
打包赏枚,在iOS 13(不含)
之前系統(tǒng)無法啟動APP
。由于提示原因是SwiftUI.framework
找不到晓猛,而且項目確實引用了這個庫,就針對引用的項目都做了適配凡辱。奇怪的是后來沒有引用這個庫的APP
也無法打開戒职,為了研究這個原因,新建項目測試透乾,最終發(fā)現(xiàn)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 中添加對應(yīng)的 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調(diào)用Swift方法傳入?yún)?shù)為nil或集合類內(nèi)部元素類型不匹配
Example:
func url(_ url: URL) {}
[Test url:nil];
func array(_ array: [String]) {}
[Test array:@[@1]];
6. UICollectionViewDiffableDataSource閃退
UITableView、UICollectionView
在iOS 13
有了新的布局和刷新方式汉操,之前一直沒用過,也不知道會有什么坑,從Bugly
上看到了一個閃退問題多次上報炊昆,上報原因是數(shù)組越界茂洒,從代碼層面分析半天也沒分析出來。后來統(tǒng)計了上報的機型采缚,發(fā)現(xiàn)都是iOS 13
的系統(tǒng)针炉,于是就拿出了我壓箱底的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
按照給出的數(shù)組越界去查找原因篡帕,實在是沒找出問題殖侵。然后發(fā)現(xiàn)有些頁面調(diào)用此API
沒有閃退,對比發(fā)現(xiàn)是因為animatingDifferences
屬性設(shè)置為了false
镰烧,鑒于此拢军,就加上這個試一下,哦吼拌滋,閃退解決了嘿朴沿。
如果修改每個調(diào)用地方的話太麻煩了,直接使用擴展解決
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)
}
}