Reputation: 6109
What I am having now is
classA.h
@interface ClassA: NSObject <DelegateA>
-(id)initWithData:(NSData*)data;
+(Stores*)makeClass:(Class) name fromData:(NSData*)data;
@property (assign) NSMutableArray *arr;
@property (assign) RXMLElement *rxmlRoot;
@end
classA.m
-(id)initWithData:(NSData*)data {
self = [super init];
if (self) {
arr = [[NSMutableArray array] retain];
rxmlRoot = [[RXMLElement elementFromXMLData:data] retain];
}
[rxmlRoot iterate:node with:^(RXMLElement *e){ <--------get warning at here
NSLog(@"element is %@",e.tag);
Detail *detail = [[[Detail alloc] init] autorelease];
[detail setLat: [e attribute:@"lat"]];
[detail setLon: [e attribute:@"lon"]];
[arr addObject:detail];
}];
return self;
}
+(classA*)makeClass:(Class) name fromData:(NSData*)data{
ClassA *classA = [[ClassA alloc] initWithData:data];
return [storeClass autorelease] ;
}
and RaptureXML.m
+ (id)elementFromXMLData:(NSData *)data {
return [[[RXMLElement alloc] initFromXMLData:data] autorelease];
}
- (id)initFromXMLData:(NSData *)data {
if ((self = [super init])) {
xml_ = [[TBXML alloc] initWithXMLData:data];
tbxmlElement_ = xml_.rootXMLElement;
}
return self;
}
Warning : Instance variable access( via 'self') results in a null pointer dereference
Question : why I am getting this warning and how to fix this issue. Please advice me on this. Thanks
Upvotes: 0
Views: 294
Reputation: 1216
Try putting all your initialization code in the
if (self) {
}
that is move the [rxmlrRoot itertate...etc. into that if statement
As a general rule, all initialization syntax (everything in the init method!) should be in that if (self) block. The reason is code outside that block would run when the super class returned nil (think else if (!self) {...). You don't want the code to continue executing if the super method (an initializer is just a regular method in O-C) was not called.
I was also taught to always have a designated initializer in my custom classes (this is the one that gets to call super init), all other initialzers in my class then call this designated initializer. Ex.
// Designated initializer
- (id)init
{
self = [super init];
if (self) {
// initialize some stuff
}
// else { something went wrong and super returned nil..
// don't put anything here
return self;
}
// Another initializer
- (id)initWithFoo:(int)foo
{
self = [self init]; // Now i call my designated initializer instead of super
if (self) {
self.foo = foo; // or something
}
}
That allows you to control all the traffic from that one point.
Upvotes: 1
Reputation: 463
Inside the block, the instance variable arr
is being accessed by reference. Due to subtle memory management rules, the access causes self
to be retained by the block.
Since if (self)
is a clue to the compiler that self
may be nil, then the implicit retain of self
by the block could cause a null pointer dereference.
To fix, check for nil and exit early:
if (!(self = [super init])) {
return nil;
}
// now it is impossible for self to be nil and cause a null pointer dereference
// when self is implicitly retained by the block
// ...continue initialization
Upvotes: 0
Reputation: 42588
In the call [rxmlRoot iterate:node with:^(RXMLElement *e){ ... }]
, what is node? It is not a local variable, or an iVar. Is it a global or does it exist somewhere else?
What ever it is, check to make sure this has been initialized.
Upvotes: 0