内存警告已释放视图控制器?
我有一个主 UIViewcontroller
(vcMain),其中有两个 UIViewControllers
是主控制器的子类。两个子类 UIViewcontrollers
(vcSub1/vcSub2) 仅显示图像和更多控件。 vcSub1 和 vcSub2 显示在 UITabBarController
中。 我已经实现了 didReceiveMemoryWarning
如下:
vcMain:
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if ([self isViewLoaded] == NO) {
// release the model, will be recreated in viewDidLoad
[_brain release], self.brain = nil;
}
}
vcSub1:
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if ([self isViewLoaded] == NO) {
// will be recreated in viewDidLoad, only exists in vcSub1
[self.zoomBrain release], [self setZoomBrain:nil];
_button = nil; // autoreleased, created programmatically
}
}
vcSub2:
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if ([self isViewLoaded] == NO) {
// nothing in here (yet)
}
}
当我第一次模拟内存警告时一切似乎都工作正常。
Received simulated memory warning.
-[AppDelegate applicationDidReceiveMemoryWarning:] [Line 81]
-[vcSub2 didReceiveMemoryWarning] [Line 102]
-[vcMain didReceiveMemoryWarning] [Line 73]
-[vcSub2 viewDidUnload] [Line 112]
-[vcMain viewDidUnload] [Line 65]
-[vcSub1 didReceiveMemoryWarning] [Line 150]
-[vcMain didReceiveMemoryWarning] [Line 73]
-[vcSub1 viewDidUnload] [Line 143]
-[vcMain viewDidUnload] [Line 65]
我可以一次又一次地这样做,没有任何问题。但是,如果我切换选项卡(从而重新加载视图)并再次模拟内存警告,我会得到以下信息:
Received simulated memory warning.
-[AppDelegate applicationDidReceiveMemoryWarning:] [Line 81]
-[vcSub2 didReceiveMemoryWarning] [Line 102]
-[vcMain didReceiveMemoryWarning] [Line 73]
-[vcSub1 didReceiveMemoryWarning] [Line 150]
-[vcMain didReceiveMemoryWarning] [Line 73]
-[vcSub1 viewDidUnload] [Line 143]
-[vcMain viewDidUnload] [Line 65]
*** -[vcSub1 isViewLoaded]: message sent to deallocated instance 0x614de80
info malloc-history 0x614de80
显示该实例是 vcSub1视图控制器。
Alloc: Block address: 0x0614de80 length: 192
Stack - pthread: 0xa0425540 number of frames: 21
0: 0x93f7f0a3 in malloc_zone_calloc
1: 0x93f7effa in calloc
2: 0x154a2d4 in class_createInstance
3: 0x13165d8 in +[NSObject(NSObject) allocWithZone:]
4: 0x13163da in +[NSObject(NSObject) alloc]
5: 0x2bf0 in -[AppDelegate application:didFinishLaunchingWithOptions:] at AppDelegate.m:47
6: 0x8dec89 in -[UIApplication _callInitializationDelegatesForURL:payload:suspended:]
7: 0x8e0d88 in -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:]
8: 0x8eb617 in -[UIApplication handleEvent:withNewEvent:]
9: 0x8e3abf in -[UIApplication sendEvent:]
10: 0x8e8f2e in _UIApplicationHandleEvent
11: 0x30b9992 in PurpleEventCallback
12: 0x13d3944 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
13: 0x1333cf7 in __CFRunLoopDoSource1
14: 0x1330f83 in __CFRunLoopRun
15: 0x1330840 in CFRunLoopRunSpecific
16: 0x1330761 in CFRunLoopRunInMode
17: 0x8e07d2 in -[UIApplication _run]
18: 0x8ecc93 in UIApplicationMain
19: 0x28f9 in main at main.m:14
20: 0x2875 in start
为什么以及如何释放我的 vcSub1 视图控制器?
I have a main UIViewcontroller
(vcMain) with two UIViewControllers
subclassed from the main one. Both subclassed UIViewcontrollers
(vcSub1/vcSub2) simply show an image and some more controls. vcSub1 and vcSub2 are displayed in a UITabBarController
.
I have implemented didReceiveMemoryWarning
like this:
vcMain:
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if ([self isViewLoaded] == NO) {
// release the model, will be recreated in viewDidLoad
[_brain release], self.brain = nil;
}
}
vcSub1:
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if ([self isViewLoaded] == NO) {
// will be recreated in viewDidLoad, only exists in vcSub1
[self.zoomBrain release], [self setZoomBrain:nil];
_button = nil; // autoreleased, created programmatically
}
}
vcSub2:
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
if ([self isViewLoaded] == NO) {
// nothing in here (yet)
}
}
When I simulate the memory warning the first time everything seems to work fine.
Received simulated memory warning.
-[AppDelegate applicationDidReceiveMemoryWarning:] [Line 81]
-[vcSub2 didReceiveMemoryWarning] [Line 102]
-[vcMain didReceiveMemoryWarning] [Line 73]
-[vcSub2 viewDidUnload] [Line 112]
-[vcMain viewDidUnload] [Line 65]
-[vcSub1 didReceiveMemoryWarning] [Line 150]
-[vcMain didReceiveMemoryWarning] [Line 73]
-[vcSub1 viewDidUnload] [Line 143]
-[vcMain viewDidUnload] [Line 65]
I can do this again and again without problems. However, if I switch tabs (and thus reload the views) and simulate the memory warning again I get this:
Received simulated memory warning.
-[AppDelegate applicationDidReceiveMemoryWarning:] [Line 81]
-[vcSub2 didReceiveMemoryWarning] [Line 102]
-[vcMain didReceiveMemoryWarning] [Line 73]
-[vcSub1 didReceiveMemoryWarning] [Line 150]
-[vcMain didReceiveMemoryWarning] [Line 73]
-[vcSub1 viewDidUnload] [Line 143]
-[vcMain viewDidUnload] [Line 65]
*** -[vcSub1 isViewLoaded]: message sent to deallocated instance 0x614de80
An info malloc-history 0x614de80
shows that the instance is the vcSub1 viewcontroller.
Alloc: Block address: 0x0614de80 length: 192
Stack - pthread: 0xa0425540 number of frames: 21
0: 0x93f7f0a3 in malloc_zone_calloc
1: 0x93f7effa in calloc
2: 0x154a2d4 in class_createInstance
3: 0x13165d8 in +[NSObject(NSObject) allocWithZone:]
4: 0x13163da in +[NSObject(NSObject) alloc]
5: 0x2bf0 in -[AppDelegate application:didFinishLaunchingWithOptions:] at AppDelegate.m:47
6: 0x8dec89 in -[UIApplication _callInitializationDelegatesForURL:payload:suspended:]
7: 0x8e0d88 in -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:]
8: 0x8eb617 in -[UIApplication handleEvent:withNewEvent:]
9: 0x8e3abf in -[UIApplication sendEvent:]
10: 0x8e8f2e in _UIApplicationHandleEvent
11: 0x30b9992 in PurpleEventCallback
12: 0x13d3944 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
13: 0x1333cf7 in __CFRunLoopDoSource1
14: 0x1330f83 in __CFRunLoopRun
15: 0x1330840 in CFRunLoopRunSpecific
16: 0x1330761 in CFRunLoopRunInMode
17: 0x8e07d2 in -[UIApplication _run]
18: 0x8ecc93 in UIApplicationMain
19: 0x28f9 in main at main.m:14
20: 0x2875 in start
Why and how was my vcSub1 viewcontroller deallocated?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您释放对象的次数太多了。假设您的属性是(保留),那么您这里有一个错误:
第一行将释放 ZoomBrain。
第二行将释放zoomBrain,然后将其设置为nil。
您将发布两次 - 您只需要第二行。如果你使用setter方法(即setZoomBrain:)那么它会自动为你释放之前的zoomBrain。
这也是同样的情况:
对
self.brain
的调用是一种不同的编写方式[self setBrain:nil];
- 同样,release 将被调用两次。在每种情况下您只需要第二行:
I think you're releasing your objects too many times. Assuming that you're property is (retain) then you've got a bug here :
The first line will release the zoomBrain.
The second line will release the zoomBrain and then set it to nil.
You're releasing it twice - you only need the second line. If you use the setter method (i.e. setZoomBrain:) then it automatically releases the previous zoomBrain for you.
The same goes for this :
The call to
self.brain
is a different way of writing[self setBrain:nil];
- again, release will be called twice.You only need the second line in each case :