开发者

releasing objects?

I'm really new to iPhone programming.

This app is a simple quiz. FirstAppDelegate.m creates an instance of QuizViewController and adds its view to the window.

#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

I thought I could release vc like I do hear since window will retain it (?) but it generated an error :

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'

...so I commented it and now it works fine. But where should I releas开发者_开发百科e vc? Here's 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

...and 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


You should create an instance variable to hold the VC. The reason you are losing it when you release it is that the window is only retaining the view and not the controller.


I thought I could release vc like I do hear since window will retain it...

Notice that you are adding the view associated to the view controller ([vc view]) to your UIWindow. That object will be retained, not your controller.

You can fix this by defining a variable in your FirstAppDelegate to store the controller there and release it in 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;
   ....
}


The views/windows do retain their child views, the view controllers retain their views, but the views don't retain their controllers. It's a "one-way" relationship, a clear has-a. This also comes in handy to prevent retain cycles.

You probably want to save the controller in an ivar in the class you alloc/init it, and release it in dealloc or when you pull the view from screen.

View controllers often get retained by other view controllers, i.e. when you push them onto a navigation stack, or put them in tabs.


If you don't mind dropping support for iOS 3.0/3.1/3.2, you can use the UIWindow.rootViewController property:

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

    return YES;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜