释放对象?
我对 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
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 release 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您应该创建一个实例变量来保存 VC。当您释放它时丢失它的原因是窗口仅保留视图而不保留控制器。
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.
请注意,您正在将与视图控制器 (
[vc view]
) 关联的视图添加到您的 UIWindow。该对象将被保留,而不是您的控制器。您可以通过在
FirstAppDelegate
中定义一个变量来存储控制器并在FirstAppDelegate
dealloc
中释放它来解决此问题。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 inFirstAppDelegate
dealloc
.视图/窗口确实保留其子视图,视图控制器保留其视图,但视图不保留其控制器。这是一种“单向”关系,明确的有一个。这对于防止循环引用也很有用。
您可能希望将控制器保存在您分配/初始化它的类中的 ivar 中,并在
dealloc
中或当您从屏幕中拉出视图时释放它。视图控制器通常会被其他视图控制器保留,即当您将它们推入导航堆栈或将它们放入选项卡时。
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.
如果您不介意放弃对 iOS 3.0/3.1/3.2 的支持,则可以使用
UIWindow.rootViewController
属性:If you don't mind dropping support for iOS 3.0/3.1/3.2, you can use the
UIWindow.rootViewController
property: