2010-01-13 158 views
1

我目前正在開發一個iPhone應用程序,它從RSS提要加載數據並將其顯示在2個UITableView中的Tab Bar應用程序中,我們稱之爲TableViewA和TableViewB。在AppDelegate中,我們有以下方法:UITableView滾動崩潰

- (void)getDataWithContext:(NSManagedObjectContext *)context 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    NSError *parseError = nil; 

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 

    XMLReader *xmlReader = [[[XMLReader alloc] initWithContext:context]autorelease]; 
    [xmlReader parseXMLFileAtURL:[NSURL URLWithString:@"http://example.com/rss.xml"] parseError:&parseError]; 
    [pool release]; 

    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
} 

在我們的applicationDidFinishLaunching:方法我們稱之爲斷開與該選擇一個新的線程:

if ([self isDataSourceAvailable] == NO) { 
    UIAlertView *noConnection = [[[UIAlertView alloc] initWithTitle:@"Connection Unavailable" message:@"The connection to the database is unavailable. The information displayed may be outdated." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease]; 
    [noConnection show]; 
} 
else{ 
    [NSThread detachNewThreadSelector:@selector(getDatawithContext:) toTarget:self withObject:context]; 
} 

TableViewControllerA是一個UITableViewController

以下方法加載TableView的數據和圖像。當上面的XML讀取器的線程退出時,將所有條目放入CoreData中,我們會收到通知並將條目從CoreData重新加載到TableView中。

TableViewControllerB是一個TableViewControllerA,它繼承了這些相同的方法並做了一些改變,從數據庫中選擇不同的條目。

- (IBAction)loadData: (id) sender{ 
    BroadwayAppDelegate *appDelegate = (BroadwayAppDelegate *) [[UIApplication sharedApplication] delegate]; 

    checkDate = [NSPredicate predicateWithFormat: @"date <= %@", 
         [NSDate date]]; 
    if ([self.showsSegmentedControl selectedSegmentIndex] == UISegmentedControlNoSegment || 
      [self.showsSegmentedControl selectedSegmentIndex] == 0){ 
     self.listContent = [CoreDataHelper searchObjectsInContext :@"Entry" :self.checkDate :@"title" :YES :appDelegate.managedObjectContext]; 
    } 
    else if ([self.showsSegmentedControl selectedSegmentIndex] == 1){ 
     self.listContent = [CoreDataHelper searchObjectsInContext :@"Entry" :self.checkDate :@"startDate" :NO :appDelegate.managedObjectContext]; 
    } 
    else if ([self.showsSegmentedControl selectedSegmentIndex] == 2){ 
     self.listContent = [CoreDataHelper searchObjectsInContext :@"Entry" :self.checkDate :@"endDate" :YES :appDelegate.managedObjectContext]; 
    } 
    else if ([self.showsSegmentedControl selectedSegmentIndex] == 3){ 
     self.listContent = [CoreDataHelper searchObjectsInContext :@"Entry" :self.checkDate :@"type" :YES :appDelegate.managedObjectContext]; 
    } 

    // create a filtered list that will contain products for the search results table. 
    self.filteredContent = [NSMutableArray arrayWithCapacity:[self.listContent count]]; 

    // restore search settings if they were saved in didReceiveMemoryWarning. 
    if (self.savedSearchTerm) 
    { 
     [self.searchDisplayController setActive:self.searchWasActive]; 
     [self.searchDisplayController.searchBar setSelectedScopeButtonIndex:self.savedScopeButtonIndex]; 
     [self.searchDisplayController.searchBar setText:savedSearchTerm]; 

     self.savedSearchTerm = nil; 
    } 

    NSError *error; 
    [appDelegate.managedObjectContext save:&error]; 


    [self.tableView reloadData]; 

} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    [self loadData:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(threadExited) name:@"NSThreadWillExitNotification" object:nil]; 

    dateFormatter = [[NSDateFormatter alloc]init]; 
    [dateFormatter setDateStyle: NSDateFormatterMediumStyle]; 
    self.title = @"Entries"; 

} 

- (void)threadExited{ 
    [self loadData:nil]; 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
    [NSThread detachNewThreadSelector:@selector(loadImages) toTarget:self withObject:nil]; 
} 
- (void) loadImages{ 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
    NSArray *coreDataEntries = [CoreDataHelper getObjectsFromContext:@"Entry" :@"title" :NO :appDelegate.managedObjectContext]; 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; 
    for (Entry *s in coreDataEntries){ 
     if (s.image == nil) { 
      NSString *URLString = [[Entry imageURLFromLink:s.link withExtension:@".jpg"]absoluteString]; 
      NSURL *imageURL = [NSURL URLWithString:URLString]; 
      NSData *imageData = [NSData dataWithContentsOfURL:imageURL]; 
      s.image = [UIImage imageWithData:imageData]; 
     } 
    } 
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; 
    [self.tableView reloadData]; 
    [pool release]; 
} 

如果當數據被重新載入或可能XML讀取器退出當用戶滾動任一的tableview應用程序崩潰。爲什麼會發生這種情況,我們該如何解決?我們已經使用提供的工具來檢查內存泄漏以及這類事情,並且我們沒有發現與崩潰相關的任何內容。

+0

您是否嘗試過使用GDB的步驟,通過這個代碼,直到你可以觀察崩潰發生?根據我的經驗,如果你能看到崩潰,那麼修復起來就容易得多,因爲根本原因通常只是通過逐步觀察你的代碼的行爲來明確。 – rpj

+0

另外,請記住,滾動表視圖會非常頻繁地調用一些表視圖委託方法:如果您在這些方法中做了任何繁重的工作,特別是如果這種提升處理共享資源,那麼您可能會嘗試訪問無效的內存。 – rpj

+0

需要一個日誌或更多東西繼續下去......我們甚至不能看到如何製作單元格,這些單元格在滾動時似乎更可能是崩潰的來源。 –

回答