开发者

Problem with initialization of object in Objective C

As a demonstration of my problem I have created small example: I have created new view-based application then I have added button to xib and connected it to an IBAction. Then I have written this class:

#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

Then I modified the created 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

What I don't understand is why, after clicking the button, there is a problem with the NSArray, which isn't initialized, although I initialize this NSArray in viewDidLoad. How could I make it work for me? I need to initialize this TaskGenerator after the view is loaded and then I will use this object in various methods. Please help me with this problem.


I'm assuming your application crashes with EXC_BAD_ACCESS. The reason for this would be that the mathPictures object has been deallocated and is no longer valid. You created it using the arrayWithObjects: method, which returns an autoreleased object. When an object is autoreleased, it is added to a pool, and when that pool is "drained", every object in it will receive a release message. Since the array hadn't been retained anywhere else, it was then deallocated, leaving the mathPictures variable pointing to free memory. To fix this, you either need to use the alloc/init methods to get a retained array, or retain the array yourself after creating it.

- (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;
}

Also, in your viewDidLoad method, you should call the super implementation first.

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


Your @property declaration creates a setter method that correctly retains the object. But, when you assign directly to the mathPictures instance variable, you're bypassing the setter, so the array doesn't get retained. Instead, you should use dot-syntax to use the property setter:

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


Do you need to alloc when you declare mathPictures & NSArray:

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

Alternatively, you could place the following line inside viewDidLoad:

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

Also, in viewDidLoad, should the [super viewDidLoad] be the first line before you do the other tasks?

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜