Управление памятью Objective-C: ошибка BAD_ACCESS - PullRequest
0 голосов
/ 03 августа 2011

Я работаю над библейским приложением для iPhone. Вот основы того, что я делаю до сих пор:

  • Мой XMLParser анализирует файл xml и создает объект Библии

  • В частности, xml хранится в каждом объекте Chapter.

  • После завершения анализа viewController берет главу из Библии и отображает ее innerHtml в UIWebview.

Это работает, но всякий раз, когда я пытаюсь получить доступ к объекту Библии за пределами - (void) viewDidLoad; либо выдает ошибку BAD_ACCESS, либо результаты того, что я запрашиваю, не читаются. Я думаю, что это проблема управления памятью ..

Вот что я делаю в 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...

}

Конечно, я был бы рад опубликовать любой другой код. Я просто не хотел перегружать страницу кодом, поэтому я вставил только там, где, как мне кажется, проблема, или, по крайней мере, там, где она возникает.

Ответы [ 3 ]

4 голосов
/ 03 августа 2011

Вы выделяете finalBible, но затем вы устанавливаете finalBible = [parser getBible], так что предыдущее распределение не имеет смысла. Кроме того, похоже, что [parser getBible] возвращает автоматически освобожденный объект, поэтому вы должны вызвать [[parser getBible] retain], чтобы убедиться, что он не покидает память.

1 голос
/ 03 августа 2011

Это именно то, что вам нужно сделать в вашем .h файле, добавьте эту строку:

@property(nonatomic, retain) Bible finalBible;

Затем в вашем .m файле добавьте эту строку вверху:

//This generates the methods (get, set) for your instance variable
@synthesize finalBible;

Затем оставьте эту строку:

finalBible = [[Bible] alloc]init];

Это потому, что если вы сохраните его, то здесь будет утечка памяти:

finalBible = [parser getBible];

Поскольку теперь вы указываете на новую ячейку памяти, а в предыдущей ячейке памяти был объект с счетом сохранения 1, предоставленным alloc init, и, поскольку больше не будет никакой ссылки на этот объект, он никогда не будет освобожден. вызывает утечку памяти.

Хотя, если вы используете эту строку:

self.finalBible = [parser getBible];

Поскольку используется установщик, установщик освобождает предыдущее значение и сохраняет новое, поэтому утечки памяти не будет, но выделять этот объект все равно будет бессмысленно.

Поскольку getBible не имеет ключевого слова new, alloc or init, он должен возвращать объект autoreleased, поэтому объект освобождается в следующем цикле выполнения (не гарантируется, но, скорее всего), поэтому вы не можете получить к нему доступ снаружи метода viewDidload().

0 голосов
/ 03 августа 2011

Вы можете решить эту проблему, сделав переменную finalBible свойством класса, используя

@ свойство (неатомное, сохраняемое) Библия finalBible; // это в .h файле @ Synthesis finalBible; // вверху файла .m

Все ссылки на «finalBible» следует указывать как «self.finalBible»

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...