如题,当程序崩溃报错为:*** 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虽好可以实现自己想要的功能,但是一定要注意关键字的问题,一不留神,问题查找相当的难受。自己的写的代码还好说问题分析还快,特别是别人写的代码,你要看懂还要理解,最烦的就是没注释,哎,程序员的痛啊!!!!
通过一系类问题追踪,自己已找到了解决此问题方法了,如果断点跟踪也没办法找到异常问题所在,可以试试分类方法重写类的实现,然后再看看堆栈信息,可能会有所发现!!!