将VC添加为UINav rootVC时,不会将内存分配给IVR

时间:2012-10-22 06:45:45

标签: objective-c ios memory-management

EDITED

这是我在编码过程中遇到的一个非常常见的问题,请看一下。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.

// Adding Landing screen landscape on mainwindow
self.landingViewController = [[LandingViewController alloc] initWithNibName:@"LandingViewController" bundle:nil];
[self.window addSubview:self.landingViewController.view];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;

}

#import <UIKit/UIKit.h>

@class RecentPlanViewController;
@class ChevronViewController;


@interface LandingViewController : UIViewController
{
 UINavigationController *navigationController;

    // custom view controllers
RecentPlanViewController *recentPlanViewController;
ChevronViewController *chevronViewController;

}

- (void)popView:(NSNotification *)notification;


@property (nonatomic,retain) UINavigationController *navigationController;
@property (nonatomic,retain) RecentPlanViewController *recentPlanViewController;
@property (nonatomic,retain) ChevronViewController *chevronViewController;
@end


self.recentPlanViewController = [[RecentPlanViewController alloc] initWithNibName:@"RecentPlanViewController" bundle:nil];

[self.recentPlanViewController loadView];   // if I skip this : Memory to recentPlanViewController's IVs not allocated.

self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.recentPlanViewController ];


#import <UIKit/UIKit.h>
@class RecentPlanCell;


@interface RecentPlanViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
IBOutlet UITableView *recentPlanTableView; // Main recent TableView
RecentPlanCell *recentPlanCell;
IBOutlet UIButton *createPlanButton;
IBOutlet UIButton *viewAllPlanButton;
BOOL isViewingAllPlans;   // Yes if view all plan pressed
}

@property (nonatomic,retain) RecentPlanCell *recentPlanCell;
@property (nonatomic,retain) IBOutlet UIButton *createPlanButton;
@property (nonatomic,retain) IBOutlet UIButton *viewAllPlanButton;

@end

以上编写的代码有两个结论。

1.如果我使用loadView方法。它调用视图控制器的视图并仅为IBOutlets分配内存,而不用于其他self.recentPlanViewController实例变量。

2.如果我跳过第二行代码,即使将其用作rootVC,它也不会为任何IVR分配内存。

请指导我,我违反的内存管理概念是什么!

由于

3 个答案:

答案 0 :(得分:2)

有一些问题:

  • 您直接致电loadView
  • 您没有显示视图控制器的视图

loadView

documentation说:

  

如果无法在故事板或nib文件中定义视图,请覆盖loadView方法以手动实例化视图层次结构并将其分配给视图属性。

  

你永远不应该直接调用这个方法[loadView]。视图控制器在请求其view属性但当前为nil时调用此方法。此方法加载或创建视图并将其分配给视图属性。

这是什么意思?

有三种方法可以为视图控制器提供视图:

  • 使用故事板
  • 使用笔尖
  • 编程

所以,既然你在谈论IBOutlet,那么必须排除第三种方式。

IBOutlet'何时'准备好'?

输入viewDidLoad

  

在视图控制器将其视图层次结构加载到内存后调用此方法。无论视图层次结构是从nib文件加载还是在loadView方法中以编程方式创建,都会调用此方法。

调用此方法后,您的IBOutlet已准备就绪,您可以安全地访问它们。

显示视图

我不知道您的视图控制器的层次结构是什么,但您可能正在重新分配navigationController而不是重复使用它。

如果从另一个视图控制器推送该视图控制器,则应执行此操作:

[self.navigationController pushViewController:self.recentPlanViewController animated:YES];

为了重用管理层次结构的navigationController(而不是重新分配)。

所以,问题是:你如何展示LandingViewController

答案 1 :(得分:1)

问题是,loadView是自动调用的,你不应该自己调用它。要调用它,您的UIViewController必须出现在屏幕上。你现在所拥有的是指向你recentPlanViewController的指针,就是这样。要调用loadViewviewDidLoadviewWillAppear,您需要执行以下操作:

[self pushViewController:self.recentPlanViewController];

IBOutlets实际出现在屏幕上之前,您不应该依赖UIViewController。如果您希望IBOutlets在开头有一些默认值,则应在init方法上传递它们,将它们保存为ivars,然后在viewDidLoad中设置它们,例如。

修改

这可能有问题:

self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.recentPlanViewController ];

因为您正在重新初始化您自己的navigationController。

编辑2:

如果您只是想显示新的UIViewController,假设您已经有效UINavigationController,则可以执行以下操作:

  [self.navigationController pushViewController:self.recentPlanViewController animated:YES];

如果您没有self.navigationController,则可以:

[self presentViewController:self.recentPlanViewController animated:YES completion:^{

}];

答案 2 :(得分:0)

解决方法是: 在视图控制器本身中关联或使用iVars。