2012-12-19 43 views
3

iOS開發初學者,我會嘗試實現一個應用程序,它顯示一個XML文件的RSS源。EXC_BAD_ACCESS與NSXMLParser和ARC

在我的UITableView類的viewDidLoad中,我使用UIActivityIndicator來等待數據加載。

但是,在應用程序將回到主線程的那一刻,我在parseXMLStart函數的末尾添加了EXC_BAC_ACCESS代碼2。我不明白爲什麼...

這裏的錯誤消息:

Thread 6 : 0-[NSXMLParser dealloc] 
Message : EXC_BAC_ACCESS (code=2, address=0xc) 
Line  : 0xbb0840: movl (%eax,%ecx), %ecx 

我不知道什麼和在哪裏是我的錯誤。我該如何解決它?


這裏是我的代碼:

=> Class Type :: UITableViewController  

>> Header 

@interface DataListViewController : UITableViewController { 
    UIActivityIndicatorView *activityView; 
    NSMutableArray *dataFromXML; 
} 

- (void)parseXMLStart; 
- (void)parseXMLDone; 

@end 

>> Main 

@implementation DataListViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.view.backgroundColor = [UIColor whiteColor]; 
    self.title = @"View 1"; 

    activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 
    activityView.center = self.view.center; 

    [self performSelectorInBackground:@selector(parseXMLStart) withObject:nil]; 

    [activityView startAnimating]; 
    [activityView setHidesWhenStopped:YES]; 

    [self.view addSubview:activityView]; 
} 

#pragma mark - UIActivityIndicator Methods 

- (void)parseXMLStart 
{ 
    // To Show the animation 
    sleep(1); 

    dataFromXML = [[NSMutableArray alloc] init]; 

    // COMMENT TO TEST /* 

    [dataFromXML addObject:@"Element 1"]; 
    [dataFromXML addObject:@"Element 2"]; 
    [dataFromXML addObject:@"Element 3"]; 

    // */ COMMENT TO TEST 

    // ------------------------------------------------------------------------------------------------------------------------------------ 

    // UNCOMMENT TO TEST 
    /* 

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"words" ofType:@"xml"]; 
    NSURL *url = [[NSURL alloc] initWithString:[[NSString stringWithFormat:@"file://%@",filePath] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]]; 

    XML2ObjectParser *parserWords = [[XML2ObjectParser alloc] parseXMLAtURL:url toObject:@"Word" parseError:nil]; 

    NSLog(@">> parserWords Items Count :: %i", parserWords.items.count); 

    for (int i = 0; i < [parserWords.items count]-1; i++) { 
     Word *aWord = [[Word alloc] init]; 
     aWord = (Word *)[[parserWords items] objectAtIndex:i]; 
     [dataFromXML addObject:aWord]; 
    } 

    NSLog(@">> dataFromXML Count :: %i", dataFromXML.count); 

    */ 
    // UNCOMMENT TO TEST 

    // -------------------------------------------------------------------------------------------------------------------------------------------- 

    // EXC_BAD_ACCESS (code=2, address=0xc) 
    // Thread 6 : 0-[NSXMLParser dealloc] 
    // 0xbad840: movl (%eax,%ecx), %ecx 

    // -------------------------------------------------------------------------------------------------------------------------------------------- 

    [self performSelectorOnMainThread:@selector(parseXMLDone) withObject:nil waitUntilDone:YES]; 
} 

- (void)parseXMLDone 
{ 
    [activityView stopAnimating]; 
    [self.tableView reloadData]; 
} 

# pragma mark - Table View Method 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return [dataFromXML count]; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *cellID = @"CellID"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID]; 

    if (cell == nil) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID]; 
    } 

    cell.textLabel.text = [dataFromXML objectAtIndex:[indexPath row]]; 

    return cell; 
} 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    DataListDetailViewController *_dataListDetailViewController = [[DataListDetailViewController alloc] init]; 

    _dataListDetailViewController.title = [dataFromXML objectAtIndex:[indexPath row]]; 

    [self.navigationController pushViewController:_dataListDetailViewController animated:YES]; 
} 

@end 
+4

幾件事情...... 1)爲什麼'XML2ObjectParser'是'NSXMLParser'的子類?它使用一個,但不作爲一個。 2)調用'alloc'而不調用某個'init'方法通常是錯誤的。 3)通過在您使用的構建/運行方案中啓用殭屍並啓用Objective-C異常的斷點,您應該能夠獲得更好的信息。 –

回答

1

它看起來對我來說,你的選擇是正確鍵入。你有@selector(parsingXMLDone)它應該是@selector(parseXMLDone)

+0

啊......好吧......從你發佈的堆棧中看,好像你的對象在你的方法完成之前就被釋放了。您是否嘗試瞭解將「waitUntilDone」更改爲YES時會發生什麼? –

1

我找到了錯誤。

這不是我的錯誤,而是ARC。

我解釋了,當解析XML時,後臺線程被終止,ARC想要釋放NSXMLParser。

這就是爲什麼它會導致EXC_BAD_ACCESS,因爲ARC想要釋放一個已經釋放的對象(AKA NSXMLParser)。

解決方案是在目標的構建階段使用標記「fno-objc-arc」來編譯我的沒有ARC的類。

請參見:NSXMLParser gives EXC_BAD_ACCESS only with ARC enabled

感謝您的幫助。