释放物体?

时间:2011-06-28 21:32:27

标签: iphone release

我是iPhone编程的新手。

这个应用程序是一个简单的测验。 FirstAppDelegate.m创建一个QuizViewController实例并将其视图添加到窗口。

#import "FirstAppDelegate.h"
#import "ResultViewController.h"
#import "QuizViewController.h"

@implementation FirstAppDelegate

@synthesize window;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions {
    UIViewController *vc = [[QuizViewController alloc] init];
    [window addSubview:[vc view]];
    [window makeKeyAndVisible];
    [vc release];

    return YES;
}

- (void)dealloc {
    [window release];
    [super dealloc];
}

@end

我以为我可以释放vc就像我听到的那样,因为窗口会保留它(?)但是它产生了一个错误:

2011-06-28 23:06:34.190 First[14289:207] -[__NSCFType foo:]: unrecognized selector sent to instance 0x4e1fc90
2011-06-28 23:06:34.193 First[14289:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType foo:]: unrecognized selector sent to instance 0x4e1fc90'

...所以我评论它,现在它工作正常。但是我应该在哪里发布vc?这是QuizViewController.h:

#import <UIKit/UIKit.h>

@interface QuizViewController : UIViewController {
    IBOutlet UILabel *questionLabel;
    IBOutlet UIButton *button1;
    IBOutlet UIButton *button2;
    IBOutlet UIButton *button3;

    int currentQuestionIndex;
    int corrects;
    NSMutableArray *questions;
    NSMutableArray *answers;
    NSMutableArray *correctAnswers;
}

- (IBAction)foo:(id)sender;

@end

...和QuizViewController.m:

#import "QuizViewController.h"

@implementation QuizViewController

- (id)init {
    NSLog(@"QuizViewController init");
    [super initWithNibName:@"QuizViewController" bundle:nil];

    questions = [[NSMutableArray alloc] init];
    answers = [[NSMutableArray alloc] init];
    correctAnswers = [[NSMutableArray alloc] init];

    [questions addObject:@"Vad betyder det engelska ordet \"though\"?"];
    [answers addObject:@"Tuff"];
    [answers addObject:@"Dock"];
    [answers addObject:@"Tanke"];
    [correctAnswers addObject:@"Dock"];

    [questions addObject:@"Vad hette frontpersonen i Popbandet Queen?"];
    [answers addObject:@"Pierre Bouviere"];
    [answers addObject:@"Freddie Mercury"];
    [answers addObject:@"Stevie Wonder"];
    [correctAnswers addObject:@"Freddie Mercury"];

    return self;
}


- (IBAction)foo:(id)sender {
    NSLog(@"foo");
}

- (void)loadView {
    NSLog(@"QuizViewController loadView");
    [questionLabel setText:[questions objectAtIndex:currentQuestionIndex]];
    [button1 setTitle:[answers objectAtIndex:currentQuestionIndex] forState:UIControlStateNormal];
    [button2 setTitle:[answers objectAtIndex:currentQuestionIndex + 1] forState:UIControlStateNormal];
    [button3 setTitle:[answers objectAtIndex:currentQuestionIndex + 2] forState:UIControlStateNormal];

    [super loadView];
}

- (void)viewDidLoad {
    NSLog(@"QuizViewController viewDidLoad");
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
    [super viewDidUnload];
}

- (void)dealloc {
    [super dealloc];
}

@end

4 个答案:

答案 0 :(得分:1)

  

我以为我可以释放vc就像我听到的那样,因为窗口会保留它...

请注意,您要将与视图控制器关联的视图([vc view])添加到UIWindow。该对象将被保留,而不是您的控制器。

您可以通过在FirstAppDelegate中定义变量以将控制器存储在那里并在FirstAppDelegate dealloc中释放它来解决此问题。

 @interface FirstAppDelegate
 .....
 @property (nonatomic, retain) QuizViewController* controller;
 .....
 @end

 @implementation FirstAppDelegate

 @synthesize window;
 @synthesize controller;

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions {
    self.controller = [[QuizViewController alloc] init] autorelease];
    [window addSubview:[vc view]];
    [window makeKeyAndVisible];

    return YES;
}

- (void)dealloc {
   ....
   [controller release]; controller = nil;
   ....
}

答案 1 :(得分:1)

您应该创建一个实例变量来保存VC。在释放它时丢失它的原因是窗口只保留视图而不是控制器。

答案 2 :(得分:0)

视图/窗口确实保留其子视图,视图控制器保留其视图,但视图不保留其控制器。这是一种“单向”关系,一种清晰的有一个。这对于防止保留周期也很方便。

您可能希望将控制器保存在您分配/初始化的类中的ivar中,并在dealloc或从屏幕拉出视图时将其释放。

视图控制器通常会被其他视图控制器保留,即将它们推送到导航堆栈时,或将它们放在选项卡中。

答案 3 :(得分:0)

如果您不介意放弃对iOS 3.0 / 3.1 / 3.2的支持,可以使用UIWindow.rootViewController属性:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions {
    UIViewController *vc = [[[QuizViewController alloc] init] autorelease];
    window.rootViewController = vc;
    [window makeKeyAndVisible];

    return YES;
}