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?
精彩评论