内存管理ARC和视图控制器

时间:2013-11-07 12:32:27

标签: ios iphone objective-c uiviewcontroller uikit

我今天正在考虑这个,现在我已经测试过我有点困惑......

当使用viewControllers将viewController推送到导航堆栈或以模态方式呈现ViewController时,我想知道内存管理。

让我们使用模态示例作为思想实验,这里是创建和呈现视图的源代码,在我的例子中,无论是否ARC都无所谓:

使用ARC:

ViewController *myViewController = [[ViewController alloc] init];  
myViewController.delegate = self;
[self presentViewController:myViewController animated:YES completion:NULL];

没有ARC:

ViewController *myViewController = [[ViewController alloc] init];  
myViewController.delegate = self;
[self presentViewController:myViewController animated:YES completion:NULL];
[myViewController release];                   //As it's now 'owned' by the presenting View controller

这是我对如何在现有ViewController上以模态方式呈现viewController的理解。

让我们举例来说,上面的代码驻留在一个方法中,当触摸一个按钮来调用它时,该方法会调用ViewController。

现在问我的问题,

我每次触摸按钮时都在调用此代码。在使用Instruments进行测试期间,我似乎没有任何泄漏。 - 但是因为我在myViewController中有NSLog语句 dealloc & viewDidLoad 方法我知道每次触摸按钮时它都会变得不稳定,但从未取消分配。

所以......

A)为什么我没有在仪器中显示泄漏或Live Bytes 上升)(当使用ARC或因为我每次去展示时都会创建一个新的viewController并泄漏旧的。

B)如果这不是内存安全的话,编写上述代码的正确方法是什么?我在Apple的示例代码和互联网上看到了这种代码片段。我(和他们)是否应该在 if 语句中包装alloc init行来检查对象是否已经创建?

即。

if(!myViewController)
{
    ViewController *myViewController = [[ViewController alloc] init];  
}
myViewController.delegate = self;
[self presentViewController:myViewController animated:YES completion:NULL];

感谢您花时间阅读和回答,我真的很想知道这一点,因为我一直在使用上面的代码创建,推送和呈现ViewControllers,并且从未注意到泄漏! - 可能要回去重写一遍!

为避免混淆请注意:delegate属性是我的UIViewController子类的自定义属性(我已经实现了委托协议),需要正确关闭Modally存在的Viewcontroller。根据编码指南。

此致 约翰

按要求编辑,创建代表:

·H

@protocol NotificationManagementViewControllerDelegate;

@interface NotificationManagementController : 
{
    __weak NSObject <NotificationManagementViewControllerDelegate> *delegate;
}
@property (nonatomic, weak) NSObject <NotificationManagementViewControllerDelegate> *delegate;
@protocol NotificationManagementViewControllerDelegate <NSObject>

@optional
- (void)didFinishSettingNotification:(NotificationManagementController *)notificationManagementController;

的.m

- (void)sendMessageToDismiss {
    if ([[self delegate] respondsToSelector:@selector(didFinishSettingNotification:)]) {
        [self.delegate didFinishSettingNotification:self];
    }
}

最后在代表们.m:

- (void)didFinishSettingNotification:(NotificationManagementController *)notificationManagementController
{
    [self dismissViewControllerAnimated:YES completion:NULL];
}

1 个答案:

答案 0 :(得分:1)

您没有因为创建新控制器而泄漏,ARC将为您释放此分配。

但是,最好为新的视图控制器创建@property。 并修改你的ie实现,如:

@property (nonatomic, strong) ViewController *myViewController;

if (!_myViewController)
    self.myViewController = [[ViewController alloc] init];  

self.myViewController.delegate = self;
[self presentViewController:_myViewController animated:YES completion:nil];

在这里,您有一个惰性属性,并且在第一次创建后不会创建新的ViewController。 但是,您需要在测试之外传递您的代理人(或任何财产)。

此外,如果您使用第一个实现并将此控制器添加到当前控制器的子视图中而没有属性,这将起作用,但您将收到泄漏。 我使用下面的代码获得了这方面的经验:

RootViewController的

- (void)viewDidLoad
{
    [super viewDidLoad];

    ViewController *myViewController = [[ViewController alloc] init]; 
    [self.view addSubview:myViewController.view];
}

myViewController将在屏幕上添加,但会立即释放而不保留对象的任何引用,因此如果您在“ViewController”中添加操作,您的应用程序将崩溃而不解释XCode。

因此,没有泄漏的正确写法是:

- (void)viewDidLoad
{
    [super viewDidLoad];

    if (!_myViewController)
        self.myViewController = [[ViewController alloc] init];

    [self.view addSubview:self.myViewController.view];
}

答案有点长,可以改进,所以不要犹豫! 希望它会帮助一些人。