如題,當程序崩潰報錯爲:*** Assertion failure in +[PLManagedObjectContext __prepareEntityPropertyLookups], /BuildRoot/Library/Caches/com.apple.xbs/Sources/PhotoLibraryServices_Sim/MobileSlideShow-3442.11.230/Sources/PLManagedObjectContext.m:1218 😧😧😧一臉蒙B
程序就是簡簡單單調用系統的UIImagePickerController ,獲取相冊圖片功能。
第一次調用都沒問題,下次再次彈出UIImagePickerController,一點擊圖片就會崩潰,如果選擇cancel都不會出現問題。
第一直覺就是找到崩潰的入口,開啓斷點跟蹤,在堆棧信息列表找也沒找到有用的信息!
花了大半天時間,也沒發現疑點之處。然後度娘,Google搜索都沒有好的信息可以解決此問題。
開始懷疑 iOS UIImagePickerController訪問相冊權限問題,查了查info.plist文件的都有相關的配置
是不是授權問題返回,採用的線程有問題,自己也參照SdWebImage的安全線程寫法做了一個宏定義,保證現在一定在主線程執行,結果還是沒有處理問題。
prepareEntityPropertyLookups 函數名稱信息中是不是UIImagePickerController在獲取圖片信息,查詢屬性信息耗時,自己又把UIImagePickerController對象dismiss,於是看了看UIImagePickerController委託信息,picker 不能自己dismiss自己,
難道自己的代碼寫的有問題,只要自己用到授權機制
dismissViewControllerAnimated的動畫寫成NO,或者不用info數據,第一次正常使用UIImagePickerController,第二次肯定崩潰。
又查了查PLManagedObjectContext 到底是什麼文件,Google一把,看到了PLManagedObjectContext是IOS私有庫PhotoLibraryServices.framework 的文件,難道IOS系統有bug。
系統出問題了,這個不是瞎扯嘛,後來看了看報錯的前綴 “Assertion failure ” ==> 斷言失敗,難道程序開啓斷言功能
查看了一下原來Xcode在debug下默認開啓斷言功能,以爲自己找到問題的所在,結果呢?
我把斷言關閉了,結果還是一樣,難道代碼裏面自己加了斷言的宏定義?
結果一樣也沒找到問題所在,時間就這樣慢慢的耗下去,難道自己寫的代碼有問題。
於是把UIImagePickerController相關的代碼移植到新的項目中測試,結果測試一點都沒問題,自己肯定自己的代碼沒問題,問題
處在自己的工程裏面,可能默寫的代碼寫的問題,太隱蔽了,沒法找到。
自己的想了想有沒有更好辦法定位呢?於是想到了分類方法可以覆蓋原類的方法,於是準備幹起來,重寫PLManagedObjectContext 的prepareEntityPropertyLookups方法
想法雖好但是呢?正如前面寫的一樣,這個PhotoLibraryServices是系統私有庫,沒法使用。咋辦呢?
這樣不行,那樣也不行,困死本寶寶啦。
於是乾脆學習NSLog宏定義方式,debug能輸出log,release不能輸出,於是讓NSAssert在debug與release都不輸出
效果依然不得解,咋辦,那就看看NSAssert具體調用了什麼方法。
NSAssertionHandler 是Foundation下NSException類文件中定義的類。
依舊分類的方式實現NSAssertionHandler方法,採用nil發送消息不會對程序崩潰,結果測試怎樣呢?
耶!居然通過了,程序也沒崩潰,一切都正常啦,問題終於得解。但是這並不是解決的問題的關鍵啊,斷言功能就這樣被我廢了不好吧,程序也不是這樣乾的。
於是就斷點跟蹤,看看程序堆棧類別到底什麼情況引起的斷言問題。
0x11faa5d47 <+920>: callq *%r15
0x11faa5d4a <+923>: movq %rax, %r10
0x11faa5d4d <+926>: movq 0x4e503c(%rip), %rsi ; "handleFailureInMethod:object:file:lineNumber:description:"
0x11faa5d54 <+933>: subq $0x8, %rsp
0x11faa5d58 <+937>: leaq 0x429bb9(%rip), %r11 ; @"%@ (%lu) has too many attributes to treat as a single bitfield"
0x11faa5d5f <+944>: movl $0x4c2, %r9d ; imm = 0x4C2
0x11faa5d65 <+950>: xorl %eax, %eax
0x11faa5d67 <+952>: movq -0x58(%rbp), %rdi
這個到底是什麼意思呢?
難道數據庫CoreData有問題?因爲PLManagedObjectContext集成與NSManagedObjectContext
@interface PLManagedObjectContext : NSManagedObjectContext
再看看自己的堆棧數據結果被我找到問題所在啦
userInfo 屬性問題,於是代碼搜一把
問題終於找到啦,原來開發人員在寫NSObject分類時候,利用runtime機制自定義的userInfo屬性。
於是把這些代碼註釋掉,程序就正常啦。
總結:
runtime雖好可以實現自己想要的功能,但是一定要注意關鍵字的問題,一不留神,問題查找相當的難受。自己的寫的代碼還好說問題分析還快,特別是別人寫的代碼,你要看懂還要理解,最煩的就是沒註釋,哎,程序員的痛啊!!!!
通過一系類問題追蹤,自己已找到了解決此問題方法了,如果斷點跟蹤也沒辦法找到異常問題所在,可以試試分類方法重寫類的實現,然後再看看堆棧信息,可能會有所發現!!!