Ash*_*row 17 memory-management objective-c uiviewcontroller ios
所以我在Crashlytics中经常看到这种崩溃,在iPad和iPad 2上运行iOS 5.看起来它是由内存警告引起的,但是堆栈跟踪没有引用我的任何应用程序代码,只是iOS构架:
0 libobjc.A.dylib objc_msgSend + 15
1 UIKit -[UIViewController purgeMemoryForReason:] + 64
2 Foundation __57-[NSNotificationCenter addObserver: selector: name: object:]_block_invoke_0 + 18
3 CoreFoundation ___CFXNotificationPost_block_invoke_0 + 70
4 CoreFoundation _CFXNotificationPost + 1406
5 Foundation -[NSNotificationCenter postNotificationName: object: userInfo:] + 66
6 Foundation -[NSNotificationCenter postNotificationName: object:] + 30
7 UIKit -[UIApplication _performMemoryWarning] + 80
8 UIKit -[UIApplication _receivedMemoryNotification] + 174
9 libdispatch.dylib _dispatch_source_invoke + 516
10 libdispatch.dylib _dispatch_queue_invoke + 50
11 libdispatch.dylib _dispatch_main_queue_callback_4CF + 156
12 CoreFoundation __CFRunLoopRun + 1268
13 CoreFoundation CFRunLoopRunSpecific + 300
14 CoreFoundation CFRunLoopRunInMode + 104
15 GraphicsServices GSEventRunModal + 156
16 UIKit UIApplicationMain + 1090
17 500px iOS main.m line 12
Run Code Online (Sandbox Code Playgroud)
我用谷歌搜索高低,但找不到任何解决方案.看起来这是由于过度释放UIViewController实例引起的,但我正在使用ARC,所以我不明白这是怎么回事.
我不知道如何处理这个问题.我甚至无法分辨哪个UIViewController子类导致了这个问题.我已经尝试在模拟器和设备上重现问题,但我找不到导致它的原因.有没有人见过这样的事情或有关于如何处理再现问题的建议?
Ash*_*row 17
我想我已经解决了这个问题.我正在考虑它,问题不在于卸载UIViewController视图,而是发布实际的低内存警告通知.我的代码中有几个实例,我打电话[[NSNotificationCenter defaultCenter] removeObserver:self].这在dealloc方法中很好,但在viewDidUnload方法中有两个这样的实例.
当我在didReceiveMemory其中一个UIViewController中的断点未被击中时,我注意到了这一点.中的代码viewDidUnload也被注销self从其他系统通知以及,详见这里.
在我确认崩溃因新更新而停止之前,我不会将此标记为已接受的答案.
更新:我已经通过Crashlytics验证问题已得到修复!
我注意到HockeyApp在iOS 5上运行的设备报告的崩溃中完全相同的堆栈跟踪.
除了dealloc之外,我从未打过电话 [[NSNotificationCenter defaultCenter] removeObserver:self],所以这不是导致崩溃的原因.
以下是我能够重现崩溃的方法:从MasterViewController我按下DetailViewController,然后通过点击后退按钮弹出它.最后,我触发内存警告并发生崩溃(仅在iOS 5上).
事实证明,DetailViewController在使用SVPullToRefresh时,由于保留周期而弹出后实例未释放:
@implementation DetailViewController
- (void) viewDidLoad
{
[super viewDidLoad];
[self.scrollView addPullToRefreshWithActionHandler:^{
[self refresh];
}];
}
@end
Run Code Online (Sandbox Code Playgroud)
由于DetailViewController未发布,它仍然注册了内存警告通知,这就是:
frame #0: 0x0004d61b MyApp`-[DetailViewController dealloc](self=0x089a5150, _cmd=0x024d2738) + 27 at DetailViewController.m:103
frame #1: 0x0227ae3d libobjc.A.dylib`_objc_rootRelease + 47
frame #2: 0x0227ae00 libobjc.A.dylib`objc_release + 48
frame #3: 0x0227c047 libobjc.A.dylib`objc_storeStrong + 39
frame #4: 0x0004e44c MyApp`__destroy_helper_block_ + 44 at DetailViewController.m:157
frame #5: 0x029b555d libsystem_sim_blocks.dylib`_Block_release + 166
frame #6: 0x0227ae00 libobjc.A.dylib`objc_release + 48
frame #7: 0x0227c047 libobjc.A.dylib`objc_storeStrong + 39
frame #8: 0x00084c8d MyApp`-[SVPullToRefreshView .cxx_destruct](self=0x08bf3af0, _cmd=0x00000001) + 525 at UIScrollView+SVPullToRefresh.m:121
frame #9: 0x0226630d libobjc.A.dylib`object_cxxDestructFromClass + 104
frame #10: 0x02270fde libobjc.A.dylib`objc_destructInstance + 38
frame #11: 0x02271015 libobjc.A.dylib`object_dispose + 20
frame #12: 0x0247a9a1 CoreFoundation`-[NSObject dealloc] + 97
frame #13: 0x00a8cdc7 UIKit`-[UIView dealloc] + 748
frame #14: 0x0227ae3d libobjc.A.dylib`_objc_rootRelease + 47
frame #15: 0x00a90b73 UIKit`-[UIView(Hierarchy) removeFromSuperview] + 194
frame #16: 0x00a8cc10 UIKit`-[UIView dealloc] + 309
frame #17: 0x00a9d6ff UIKit`-[UIScrollView dealloc] + 405
frame #18: 0x013ab36c Foundation`NSKVODeallocate + 105
frame #19: 0x0227ae3d libobjc.A.dylib`_objc_rootRelease + 47
frame #20: 0x00b21c12 UIKit`-[UIViewController setView:] + 447
frame #21: 0x00b21885 UIKit`-[UIViewController unloadViewForced:] + 117
frame #22: 0x00b2180b UIKit`-[UIViewController unloadViewIfReloadable] + 41
frame #23: 0x00b256ff UIKit`-[UIViewController purgeMemoryForReason:] + 75
frame #24: 0x00b2563b UIKit`-[UIViewController didReceiveMemoryWarning] + 41
frame #25: 0x00b2560d UIKit`-[UIViewController _didReceiveMemoryWarning:] + 33
frame #26: 0x0141ca29 Foundation`__57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 40
frame #27: 0x02443855 CoreFoundation`___CFXNotificationPost_block_invoke_0 + 85
frame #28: 0x02443778 CoreFoundation`_CFXNotificationPost + 1976
frame #29: 0x0136119a Foundation`-[NSNotificationCenter postNotificationName:object:userInfo:] + 98
frame #30: 0x0136db03 Foundation`-[NSNotificationCenter postNotificationName:object:] + 55
frame #31: 0x00a64cf4 UIKit`-[UIApplication _performMemoryWarning] + 91
frame #32: 0x00a64e00 UIKit`-[UIApplication _receivedMemoryNotification] + 180
frame #33: 0x00a64f98 UIKit`__block_global_0 + 36
frame #34: 0x029f1450 libdispatch.dylib`_dispatch_source_invoke + 719
frame #35: 0x029edcc4 libdispatch.dylib`_dispatch_queue_invoke + 66
frame #36: 0x029ee4cf libdispatch.dylib`_dispatch_main_queue_callback_4CF + 295
frame #37: 0x023af803 CoreFoundation`__CFRunLoopRun + 2003
frame #38: 0x023aed84 CoreFoundation`CFRunLoopRunSpecific + 212
frame #39: 0x023aec9b CoreFoundation`CFRunLoopRunInMode + 123
frame #40: 0x038d07d8 GraphicsServices`GSEventRunModal + 190
frame #41: 0x038d088a GraphicsServices`GSEventRun + 103
frame #42: 0x00a5a626 UIKit`UIApplicationMain + 1163
frame #43: 0x00002b82 MyApp`main(argc=1, argv=0xbffff318) + 178 at main.m:15
Run Code Online (Sandbox Code Playgroud)
或者用英语:SVPullToRefreshView由于视图被卸载而释放实例.由于SVPullToRefreshView实例是最后一个持有DetailViewController对它的引用的对象,因此它被释放,然后被释放.但是purgeMemoryForReason:仍然使用刚刚释放的视图控制器来处理事务(即访问实例变量),因此崩溃.
一旦确诊,解决方案非常简单:首先避免保留周期.
@implementation DetailViewController
- (void) viewDidLoad
{
[super viewDidLoad];
__typeof__(self) __weak weakSelf = self;
[self.scrollView addPullToRefreshWithActionHandler:^{
[weakSelf refresh];
}];
}
@end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3093 次 |
| 最近记录: |