2010-08-04 6 views
2

저는 Core Data 작업에 익숙하지 않고 UITableView로 작업하고 있습니다. UISegmentedController가있는 툴바가 있는데 선택한 인덱스를 기반으로 UITableView의 항목을 필터링하려고합니다. 즉, "Core"에 저장된 Books를 표시하는 UITableView와 "English", "Spanish"및 "French"로 책을 표시 할 세그먼트가있는 UISegmentedController가 있다고 가정합니다.Core Data, UITableView 및 UISegmentedControl

모든 것을 얻기 위해 여기에 접근하는 방법은 무엇입니까? 세그먼트 중 하나를 클릭하면 UISegmentedControl의 대상에서 무엇을 변경하면됩니까?

죄송합니다. 어리석은 질문이라면 죄송합니다.

답변

6

별도의NSFetchedResultsController을 각 세그먼트에 사용합니다. 이렇게하면 각 세그먼트에 내장 된 캐시를 활용하고 성능을 향상시킬 수 있습니다.

애플 문서 (및 제 도서) 외에도 PragPub 잡지의 내 기사 Touching The Core에서 해당 내용을 읽을 수 있습니다.

+0

나는 당신이 이미 커뮤니티에 너무 많은 것을주는 누군가와 마찬가지로, 나는 당신이 나의 것과 같은 질문에 대답 할 수있는 시간을 갖는 것을 절대적으로 놀라게합니다. 백만 달러 감사합니다! –

+0

Marcus, 이것을 구현하는 가장 깨끗한 방법은 무엇입니까? 세 개의 세그먼트가 있다면 세 개의 FRC가 필요하며 tableview 코드에 모든 switch() case : 문을 포함시키는 것은 그리 좋지 않을 것입니다. 아마도 개별 세그먼트에 해당하는 레이블을 사용하여 'typedef enum'을 만든 다음 적절한 인덱스의 클래스에있는 NSArray에 FRC를 추가하십시오. 그렇다면'switch() case'가있을 곳에'[self.frcArray objectAtIndex : [segControl selectedSegmentIndex]]'와 같은 것을 참조하면됩니다. 아니면 더 깨끗한 방법이 있을까요? –

+1

은 그것들을 iVars로 가지고 있고 'currentFRC' iVar를 가지고있다. 세분화 된 컨트롤을 탭하면 'currentFRC'가 가리키는 것을 전환하고 tableView에 다시로드하도록 지시합니다. 다른 모든 것은'currentFRC'와 대화하고 여러분의 델리게이트 메소드에 체크를해서'currentFRC'가 아닌 어떤 메시지도 무시합니다. –

0

각 필터마다 3 개의 다른 배열을 사용하는 것이 좋습니다. 필터를 어딘가에 캐시하여 사용자가 필터를 선택할 때 지연되지 않도록하십시오. CoreData 저장소에서 찾고있는 정보를 찾으려면 NSPredicate를 사용하십시오.

+1

핵심 데이터가있는 배열을 사용하면 작성해야하는 것보다 더 많은 코드가 생성됩니다. NSFetchedResultsController를 사용하는 것이 더 좋은 방법이다. –

+0

정식 주목 : 특히 NSFetchedResultsController가 일종의 캐싱을 사용하는 것을 좋아합니다. 대부분의 데이터는 동적이므로 대부분의 경우 NSMutableArrays에서 생각하는 것 같습니다. – PaulWoodIII

+0

동적 데이터가있는 경우에도 인 메모리 저장소가있는 코어 데이터와 NSFetchedResultsController는 거의 모든 상황에서 코드가 적어지고 성능이 향상 될 것입니다. 생각할 거리. –

0

세그먼트를 클릭했을 때을 사용할 수 있습니다. 다른 perdicate를 설정하고 다시 가져 오기를 수행하십시오.

+0

이 접근법에 대한 샘플 코드는 어디에서 찾을 수 있습니까? –

+0

읽기 : http://developer.apple.NSFetchedResultsController 생성 및 사용에 대한 자세한 내용은/iphone/library/documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html을 참조하십시오. – jamapag

+1

하나만 사용하면 캐시의 이점을 잃게됩니다. 각 세그먼트마다 하나를 사용하는 것이 더 좋습니다. –

0

위의 Marcus의 가이드 라인을 사용하여 다음과 같이 구현했습니다 (새로운 접근 방식이므로 최선의 방법이 아닐 수 있습니다). 나는 'open', 'in progress'및 'closed'에 대한 세 가지 옵션을 가진 세그먼트 컨트롤러를 가지고있다.

ViewController.h에서 세그먼트 옵션 각각에 대해 iVar를 만들고 현재 컨트롤러를 저장할 주 컨트롤러에 대해 하나의 iVar를 만듭니다.

@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController; 

@property (nonatomic, retain) NSFetchedResultsController *inprogressFetchedResultsController; 
@property (nonatomic, retain) NSFetchedResultsController *openFetchedResultsController; 
@property (nonatomic, retain) NSFetchedResultsController *closedFetchedResultsController; 

ViewController.m에서 이러한 컨트롤러의 지연로드를위한 메소드를 만들어야하므로 총 3 개가 있습니다. 그들은 술어와 cacheName을 제외하고는 기본적으로 같습니다. 아래에 하나만 보여 줬습니다.

- (NSFetchedResultsController *)closedFetchedResultsController 
{ 
    if (_closedFetchedResultsController != nil) { 
     return _closedFetchedResultsController; 
    } 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 

    // Edit the entity name as appropriate. 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Ticket" inManagedObjectContext:self.managedObjectContext]; 
    [fetchRequest setEntity:entity]; 

    // Set the batch size to a suitable number. 
    [fetchRequest setFetchBatchSize:20]; 

    // Edit the sort key as appropriate. 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"priority.name" ascending:NO]; 
    NSArray *sortDescriptors = @[sortDescriptor]; 

    [fetchRequest setSortDescriptors:sortDescriptors]; 
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"status = 'Closed'"]; 
    [fetchRequest setPredicate:predicate]; 

    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"priority.name" cacheName:@"ClosedTickets"]; 
    aFetchedResultsController.delegate = self; 

    self.closedFetchedResultsController = aFetchedResultsController; 

    NSError *error = nil; 
    if (![self.closedFetchedResultsController performFetch:&error]) { 
     // Replace this implementation with code to handle the error appropriately. 
     // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 

    return _closedFetchedResultsController; 
} 

변경 될 때 가져온 결과 컨트롤러를 변경하고 테이블을 다시로드하도록 세그먼트에 대한 IBAction을 만듭니다.

- (IBAction)statusChanged:(id)sender { 
    switch (self.segmentControl.selectedSegmentIndex) { 
     case 0: 
      self.fetchedResultsController = self.inprogressFetchedResultsController; 
      break; 
     case 1: 
      self.fetchedResultsController = self.openFetchedResultsController; 
      break; 
     case 2: 
      self.fetchedResultsController = self.closedFetchedResultsController; 
      break; 
     default: 
      break; 

    } 
    [self.tableView reloadData]; 
} 

그게 전부 야!

N.B. 또한이 행을 내 ViewDidLoad 메서드에 추가하여 처음에는 올바른 옵션을 fetchedResultsController에로드했습니다.

self.fetchedResultsController = self.inprogressFetchedResultsController; 
관련 문제