【iOS】iOS崩潰總結
一、前言
之前寫了一篇博文《【Flutter】程序報錯導致的灰屏總結》,瀏覽量、收藏率和點贊量還挺高,還被收錄了,就想著總結一下iOS崩潰
,這個也是在iOS面試中經常被問到的。
在 iOS 開發過程中,導致 App 崩潰的原因多種多樣,大致可以分為以下幾大類,
還是很想說,代碼規范很重要,代碼格式化也能方便我們查找BUG!!!
二、內存相關問題
-
訪問野指針(野地址)
- 訪問已經被釋放的對象(Use After Free)
- 常見崩潰提示:
EXC_BAD_ACCESS
、SIGSEGV
-
內存泄漏造成系統回收進程(OOM)
- 未釋放的內存持續增長,導致系統強制殺掉進程
- 通常無法捕獲崩潰日志,但系統會記錄在
JetsamEvent
中
-
循環引用
block
中引用self
、delegate
沒有用weak
,導致對象無法釋放
三、多線程問題
-
👉🏻 線程安全問題
- 多線程讀寫同一數據結構,導致崩潰或數據錯亂
-
👉🏻 死鎖
- dispatch_sync 嵌套調用自己,或等待永遠不會結束的任務
-
👉🏻 后臺線程更新 UI
- UIKit 只能在主線程使用,在子線程操作 UI 會崩潰
四、數組、字典越界或非法數據
-
👉🏻 數組越界
NSArray *array = @[]; NSLog(@"%@", array[1]); // 崩潰
-
👉🏻 向不可變字典中插入 nil
[@{@"key": nil} mutableCopy]; // 崩潰
-
👉🏻 非法類型轉換
[someObject stringByAppendingString:@"test"]
,但 someObject 實際是 NSNull
五、KVO/KVC 相關
-
👉🏻 KVO 崩潰
- 重復添加或移除觀察者
- 在對象釋放前未移除觀察者
- 修改未定義 keyPath
-
👉🏻 KVC 崩潰
setValue:forKey:
時 key 錯誤- 對私有變量或不存在屬性賦值
六、UI相關問題
-
👉🏻 約束沖突導致 UI 崩潰
- AutoLayout 添加了沖突的 constraint
-
👉🏻 Storyboard / XIB 使用錯誤
- IBOutlet 未連接或連接錯誤
- 控件在 XIB 中已刪除,但代碼中仍引用
-
👉🏻 未處理的手勢或交互崩潰
- 比如使用
UIPanGestureRecognizer
時 target 指針已釋放
- 比如使用
七、文件和路徑操作問題
-
👉🏻 文件路徑為空或錯誤
- 使用
NSString *path = nil; [NSData dataWithContentsOfFile:path];
- 使用
-
👉🏻 訪問沙盒外非法路徑
- iOS 不允許訪問 App 沙盒外的文件路徑
八、網絡或 JSON 解析異常
-
👉🏻 JSON 結構變化或數據缺失
- 使用
NSJSONSerialization
時返回了 null - 使用 Model 框架(如 YYModel、MJExtension)時解析 nil 或錯誤類型字段
- 使用
九、未捕獲的異常
- 👉🏻 未使用
try-catch
包裹潛在異常代碼(如 NSException) - 👉🏻 使用斷言(NSAssert)在 Release 模式中崩潰
十、符號錯誤 / 動態庫加載失敗
-
👉🏻 dlsym 找不到符號
- 使用動態庫(如 C 語言、Go 編譯為 static lib)時忘記導出符號或鏈接失敗
-
👉🏻 調用系統私有 API
- 在審核或某些系統中崩潰
十一、其他系統行為
-
👉🏻 App 被系統強制終止
- 使用過多內存、后臺違規行為等
- iOS 低電量或資源緊張時殺掉后臺 App
-
👉🏻 權限未申請導致崩潰
- 相機、麥克風、定位等未正確配置權限描述
十二、總結&工具
👉🏻 總結
1. 內存相關問題
- 針對于內存相關的崩潰,要養成良好的開發習慣,
定期使用Instruments排查一下,還有就是內存泄露或者暴漲,可以在基類的銷毀方法里面打印一下delloc
,如果頁面銷毀沒有打印,及時檢查一下相關的邏輯, - 還有一些導致內存暴漲的,比如加載大圖,如果使用
imageNamed:
會緩存,可以使用imageWithContentsOfFile:
; - 還有可以復用的場景,比如自定義的試圖View;
2. 多線程問題
- 關于線程不安全訪問,可以用 dispatch_queue 同步訪問共享資源,也可以用 @synchronized 或 NSLock 等鎖機制,還可以封裝線程安全類;
- 對于死鎖,避免 dispatch_sync 嵌套調用當前 queue,使用主線程 dispatch_async 更新 UI
- 在子線程更新UI,可以使用
dispatch_async(dispatch_get_main_queue(), ^{ // UI操作 });
3. 集合類崩潰問題
這個就很好解決了,網上有封裝好的安全插入或者存儲的庫,都是使用runtime
寫的。
4. KVO / KVC 崩潰
- 可以封裝 KVO,推薦使用
FBKVOController
,iOS 11 起建議使用NSKeyValueObservation
替代手動 add/remove; - (void)setValue:forUndefinedKey:
中打日志避免崩潰,對 model 層添加@property
完整定義,不讓非法 key 存在;
5. UI 崩潰 & 防護
- 針對于Storyboard/XIB 連接錯誤,每次修改 IBOutlet 后編譯驗證,控件刪除時一并移除 IBOutlet;
- AutoLayout 崩潰,設置約束時避免沖突(使用 >=、<= 等)
6. 文件/路徑/JSON 解析
- 針對于nil或者非法值,可以使用
fileExistsAtPath
- 如果是JSON 解析字段缺失或類型不匹配,可以使用 isKindOfClass 判斷類型,還可以封裝 Model 層容錯代碼(如缺字段時默認值)
7. 權限問題
- 一個是添加plist權限字段
- 還有就是在使用前,做一下權限的判斷;
8. 其他高風險點
- 可以使用斷言
- 使用
@try @catch
,但是我不建議使用@try @catch
,這樣會導致問題一直無法被暴露
👉🏻 工具
工具 | 功能 |
---|---|
Xcode Debugger | 崩潰堆棧分析、調試器跟蹤 |
Crashlytics | 崩潰日志收集平臺 |
Bugly / Sentry | 支持符號化和用戶設備統計 |
Instruments | 內存泄漏、對象分配分析 |
Address Sanitizer | 運行時檢測內存訪問越界等問題 |
十三、關于作者(ZFJ_張福杰)
- 官網:https://zfjsafe.com
- 博客:https://zfj1128.blog.csdn.net
- Github:https://github.com/zfjsyqk
- Gitee:https://gitee.com/zfj1128
- 打賞:https://zfjsafe.com/paycode