内存警告已释放视图控制器?

发布于 2024-11-05 03:54:15 字数 3481 浏览 5 评论 0原文

我有一个主 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

萌逼全场 2024-11-12 03:54:15

我认为您释放对象的次数太多了。假设您的属性是(保留),那么您这里有一个错误:

[self.zoomBrain release]
[self setZoomBrain:nil];

第一行将释放 ZoomBrain。

第二行将释放zoomBrain,然后将其设置为nil。

您将发布两次 - 您只需要第二行。如果你使用setter方法(即setZoomBrain:)那么它会自动为你释放之前的zoomBrain。

这也是同样的情况:

[_brain release];
self.brain = nil; 

self.brain 的调用是一种不同的编写方式 [self setBrain:nil]; - 同样,release 将被调用两次。

在每种情况下您只需要第二行:

self.brain = nil;

I think you're releasing your objects too many times. Assuming that you're property is (retain) then you've got a bug here :

[self.zoomBrain release]
[self setZoomBrain:nil];

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 :

[_brain release];
self.brain = nil; 

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 :

self.brain = nil;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文