释放对象?

发布于 2024-11-17 12:12:22 字数 3172 浏览 1 评论 0原文

我对 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

極樂鬼 2024-11-24 12:12:22

您应该创建一个实例变量来保存 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.

妳是的陽光 2024-11-24 12:12:22

我想我可以像我听到的那样释放 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;
   ....
}

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;
   ....
}
吝吻 2024-11-24 12:12:22

视图/窗口确实保留其子视图,视图控制器保留其视图,但视图不保留其控制器。这是一种“单向”关系,明确的有一个。这对于防止循环引用也很有用。

您可能希望将控制器保存在您分配/初始化它的类中的 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.

一笔一画续写前缘 2024-11-24 12:12:22

如果您不介意放弃对 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;
}

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文