2010-01-13 5 views
1

현재 RSS 피드에서 데이터를로드하고이를 2 개의 UITableViews에있는 Tab Bar Application에 표시하는 iPhone 응용 프로그램을 개발 중입니다. 우리는이를 TableViewA 및 TableViewB라고 부릅니다. 우리의 아래 applicationDidFinishLaunching에서UITableView Scrolling Crash

- (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; 
} 

: 다음 AppDelegate에 우리는 다음과 같은 방법을

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]; 
} 

사용자가 데이터를 다시로드 할 때 tableview를 스크롤하거나 XML 판독기를 종료 할 때 응용 프로그램이 충돌합니다. 왜 이런 일이 일어나고 어떻게 해결할 수 있습니까? 제공된 도구를 사용하여 메모리 누수 여부를 확인했으며 충돌과 관련이없는 것으로 확인되었습니다.

+0

당신이 관찰 할 수있을 때까지이 코드를 단계별로 GDB를 사용하여 시도 되세요 충돌이 일어난다 고요? 내 경험에 따르면 크래시를 볼 수 있다면 문제를 해결하는 것이 훨씬 쉽습니다. 근본 원인은 대개 코드를 단계별로 실행하는 방식을 통해 간단히 알 수 있습니다. – rpj

+0

또한 테이블 뷰를 스크롤하면 테이블 뷰 델리게이트 메소드 중 일부가 자주 호출된다는 점을 기억하십시오. 이러한 메소드에서 과도한 작업을 수행하는 경우, 특히 공유 리소스를 해제하는 것이 특히 어려울 수 있습니다. 잘못된 메모리에 액세스하십시오. – rpj

+0

계속하려면 로그 나 뭔가가 더 필요합니다 ... 또한 스크롤하는 동안 충돌의 원천이 될 것 같은 셀이 어떻게 만들어 졌는지도 볼 수 없습니다. –

답변