Objective-C memory management: BAD_ACCESS error
I'm working on a bible iPhone app. Here are the basics of what I'm doing so far:
My XMLParser parses an xml file and creates a Bible object
Specifically, the xml is stored in each Chapter object.
Once parsing is done, the viewController grabs a Chapter from the Bible and displays its innerHtml in a UIWebview.
This works, but whenever开发者_如何学运维 I try to access the Bible object outside of -(void)viewDidLoad; it either gives me a BAD_ACCESS error, or the results for what I'm asking for is unreadable. I think this is a memory management problem..
Here's what I'm doing in the viewController
- (void)viewDidLoad
{
[super viewDidLoad];
//Create parser and XML data object.
//Then, parse that data
finalBible = [[Bible alloc]init];
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"KJV" ofType:@"html"];
NSData *myData = [NSData dataWithContentsOfFile:filePath];
//INT I WANTED TO USE TO ITERATE WHEN BUTTON WAS PRESSED TO ADVANCE TO NXT CHAPTER
chapToShow = 2;
parser = [[XMLParser alloc] init];
nsParser = [[NSXMLParser alloc] initWithData:myData];
//set delegate for NSXMLParser
[nsParser setDelegate:parser];
//PARSE THE XML FILE AND BUILD BIBLE OBJECT - PARSED OK!!
if ([nsParser parse]) {
NSLog(@"Parsed with no errors!! :)");
}else{
NSLog(@"Error parsing document");
}
//IT SEEMS MY PROBLEMS MAY BE IN THIS TRADE OFF.
//I WANT TO STORE THE PARSER'S BIBLE IN THIS NEW BIBLE OBJECT.
finalBible = [parser getBible];
//Test querying bible via pullVerse method - IT WORKS!!
NSLog(@"%@",[finalBible pullVerse:@"65.021.000"]);
NSString *firstChap = [[[[finalBible getTestament:0]getBook:@"Genesis"]getChapterWithInt:3]getInnerHtml];
//Try and load Genesis 1 - THIS WORKS!!
NSLog(@"...Loading Genesis 1...");
[bibleView loadHTMLString:firstChap baseURL:nil];
//LOADING THE VERSION WORKS HERE!!
NSLog(@"Version = %@", [finalBible getVersion]);
}
- (IBAction)buttonPressed:(id)sender {
NSLog(@"Now reading chapter %d", chapToShow);
//HERE I'M TRYING TO GET THE BIBLE VERSION BUT THE APP CRASHES AS A RESULT
NSLog(@"Testing the bible: Version = %@ \n OK", [finalBible getVersion]);
//NOTE: I've even tried [[parser getBible] getVersion] and it still doesn't work.
// I don't release the parser till the view's dealloc method, so I'm not sure why I
// can't access it here...
}
Of course, I'd be happy to post any other code. I just didn't want to over-stuff the page with code, so I pasted only where I think the problem lies, or at least where it's occurring.
You allocate finalBible, but then you set finalBible = [parser getBible]
so the previous allocation is pointless. Also, it appears as though [parser getBible]
returns an autoreleased object, so you should call [[parser getBible] retain]
to make sure it does not leave memory.
This is exactly what you need to do in your .h file add this line:
@property(nonatomic, retain) Bible finalBible;
Then in your .m file add this line at the top:
//This generates the methods (get, set) for your instance variable
@synthesize finalBible;
Then drop this line:
finalBible = [[Bible] alloc]init];
This is because if you keep it, there will be a memory leak right here:
finalBible = [parser getBible];
Because now you are pointing to a new memory location, and the previous memory location had an object with a retain count of 1 provided by alloc init, and since there will no longer be any reference to this object it will never be released causing a memory leak.
Although if you use this line:
self.finalBible = [parser getBible];
Because that uses the setter, a setter releases the previous value and retains the new one, so there would not be a memory leak, but it would still be pointless to allocate that object.
Since getBible does not have the new, alloc or init
keyword it should return an autoreleased
object, which is why the object is released in the next run loop (not guaranteed but most likely), which is why you cannot access it outside of the viewDidload()
method.
You can resolve this problem by making "finalBible" variable a property of the class using
@property(nonatomic, retain) Bible finalBible; //this is in the .h file @synthesis finalBible; // at the top of .m file
All the reference to "finalBible" should be made as "self.finalBible"
精彩评论