【问题标题】:Problem with initialization of object in Objective CObjective C中对象初始化的问题
【发布时间】:2011-03-26 23:50:09
【问题描述】:

作为我的问题的演示,我创建了一个小示例:我创建了新的基于视图的应用程序,然后我将按钮添加到 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,然后我会在各种方法中使用这个对象。 请帮我解决这个问题。

【问题讨论】:

  • 在提出问题时,您应该发布您得到的错误或意外结果,以及如果您的程序崩溃时的崩溃日志。你说数组没有初始化,但不是 does 发生了什么。

标签: iphone objective-c cocoa-touch nsarray


【解决方案1】:

我假设您的应用程序因 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]);
}

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      在声明mathPictures & NSArray时是否需要alloc:

      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] 放在您执行其他任务之前的第一行?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-08-13
        • 1970-01-01
        • 1970-01-01
        • 2010-09-14
        • 1970-01-01
        • 2014-10-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多