Objective C中对象初始化的问题

时间:2011-03-26 23:50:10

标签: iphone objective-c cocoa-touch nsarray

作为我的问题的演示,我创建了一个小例子:我创建了新的基于视图的应用程序,然后我将按钮添加到xib并将其连接到IBAction。然后我写了这堂课:

#import <Foundation/Foundation.h>
@interface TaskGenerator : NSObject {   
    NSArray* mathPictures;
}

- (TaskGenerator*)init;
@property(retain,nonatomic) NSArray* mathPictures;

@end

#import "TaskGenerator.h"
@implementation TaskGenerator

@synthesize mathPictures;

- (TaskGenerator*)init
{
    self = [super init];
    if (self) 
    {
        mathPictures = [NSArray arrayWithObjects:@"0.png",@"1.png",@"2.png",@"3.png",@"4.png",@"5.png",nil];
    }
    return self;
}
@end

然后我修改了创建的viewController:

#import <UIKit/UIKit.h>
#import "TaskGenerator.h"

@interface NechapackaViewController : UIViewController {
    TaskGenerator *taskGen;
}
-(IBAction)vypis:(id)sender;
@property(nonatomic,retain) TaskGenerator *taskGen;
@end


#import "NechapackaViewController.h"
#import "TaskGenerator.h"
@implementation NechapackaViewController

@synthesize taskGen;

- (void)viewDidLoad {
    taskGen = [[TaskGenerator alloc] init];
    printf("%d\n",[taskGen.mathPictures count]);
    [super viewDidLoad];
}

-(IBAction)vypis:(id)sender
{
    printf("%d\n",[taskGen.mathPictures count]);
}

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

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

@end

我不明白为什么在点击按钮后,NSArray存在问题,虽然我在viewDidLoad中初始化了这个NSArray,但是没有初始化。我怎么能让它对我有用?我需要在加载视图后初始化此TaskGenerator,然后我将在各种方法中使用此对象。 请帮我解决这个问题。

3 个答案:

答案 0 :(得分:4)

我假设你的应用程序崩溃了EXC_BAD_ACCESS。原因是mathPictures对象已被释放并且不再有效。您使用arrayWithObjects:方法创建了它,该方法返回一个自动释放的对象。对象自动释放时,会将其添加到池中,当该池“耗尽”时,其中的每个对象都将收到release消息。由于数组未在其他任何地方保留,因此将其解除分配,使mathPictures变量指向空闲内存。要解决此问题,您需要使用alloc / init方法来获取保留的数组,或者在创建数组后自己保留数组。

- (TaskGenerator*)init {
    self = [super init];
    if (self) {
        mathPictures = [[NSArray alloc] initWithObjects:@"0.png",@"1.png",@"2.png",@"3.png",@"4.png",@"5.png",nil];
    }
    return self;
}

另外,在viewDidLoad方法中,您应该首先调用超级实现

- (void)viewDidLoad {
    [super viewDidLoad];
    taskGen = [[TaskGenerator alloc] init];
    printf("%d\n",[taskGen.mathPictures count]);
}

答案 1 :(得分:0)

您的@property声明会创建一个正确保留对象的setter方法。但是,当您直接分配给mathPictures实例变量时,您绕过了setter,因此不会保留该数组。相反,您应该使用点语法来使用属性setter:

self.mathPictures = [NSArray arrayWithObjects:@"0.png",@"1.png",@"2.png",nil];

答案 2 :(得分:-1)

你申报mathPictures&amp;时需要分配吗? NSArray的:

NSArray *mathPictures = [[NSArray alloc] initWithObjects:@"0.png", @"1.png", @"2.png", ..., nil];

或者,您可以将以下行放在viewDidLoad中:

mathPictures = [[NSArray arrayWithObjects:@"0.png", @"1.png", @"2.png", ..., nil] retain];

另外,在viewDidLoad中,在执行其他任务之前,[super viewDidLoad]应该是第一行吗?