2012-07-04 2 views
3

CoreData 탐색을위한 일반적인보기/클래스 집합이 있지만 해당 특성 중 하나의 특성에 변경 사항을 저장 한 후 가져온 결과 컨트롤러의 정렬 순서에 문제가 있습니다. 나열된 개체.나열된 개체 중 하나를 저장 한 후 NSFetchedResultsController가 손상된 정렬

- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath { 
    id objectInCell = [self.fetchedResultsController objectAtIndexPath: indexPath]; 
    ManagedObjectDetailTableViewController *dvc = [[ManagedObjectDetailTableViewController alloc] 
        initWithStyle: UITableViewStyleGrouped]; 
    dvc.detailItem = objectInCell; 
    [self.navigationController pushViewController: dvc animated: YES]; 
} 
: I는 다음과 같이 상세 테이블 뷰 컨트롤러 밀어이있는 tableview 컨트롤러 didSelectRowAtIndexPath에서

- (void) setupFetchedResultsController { 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName: self.entityToList]; 
    request.predicate = self.entitySelectionPredicate; // Typically nil 
    request.sortDescriptors = self.entitySortDescriptorList; 
    self.fetchedResultsController = [[NSFetchedResultsController alloc] 
       initWithFetchRequest: request 
       managedObjectContext: self.contextForEntity 
       sectionNameKeyPath: self.keyPathForSections 
       cacheName: nil]; /* Not chacheing */ 
} 

: I과 같은 내 페치 결과 컨트롤러 설정 내 테이블 뷰 컨트롤러 viewWillAppear:에서

ManagedObjectDetailTableViewController에는 각 속성 및 각 관계에 대한 행이 있습니다. didSelectRowAtIndexPath에서 I는 행을 포함하는 경우 ManagedObjectAttributeEditViewController 뷰 컨트롤러에 밀어 특성이 선택된다 :

- (void) tableView: (UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath { 
    // Section 0 has the attributes for the 'detailItem' object alphabetically by name 
    if(indexPath.section == 0) { 
     ManagedObjectAttributeEditViewController *evc = [[ManagedObjectAttributeEditViewController alloc] 
        initWithNibName: @"ManagedObjectAttributeEditViewController" bundle: nil]; 
     evc.editedObject = self.detailItem; 
     evc.delegate = self; 
     // Figure out from the row which attribute was selected 
     NSEntityDescription *entity = self.detailItem.entity; 
     NSDictionary *attributes = entity.attributesByName; 
     NSArray *keys = [attributes allKeys]; 
     keys = [keys sortedArrayUsingSelector: @selector(compare:)]; 
     NSString *key = [keys objectAtIndex: indexPath.row]; 
     evc.editedFieldKey = key; 
     [self.navigationController pushViewController: evc animated: YES]; 
    // The other sections are the relationships for the 'detailItem' object 
    } else { 
     // Code omitted as not relevant for the error. 
    } 
} 

ManagedObjectAttributeEditViewController이 속성 값의 수정을 허용하는 등의 텍스트 필드를 갖는다.

- (IBAction) save { 
    id valueFromView; 
    NSAttributeType type = [self typeForEditedAttribute]; 
    switch(type) { 
    case NSDateAttributeType: 
     valueFromView = self.datePicker.date; 
     break; 
    case NSStringAttributeType: 
     if([self.fieldKeyTester shouldUseTextViewForKey: self.editedFieldKey inEntity: self.editedObject.entity.name]) { 
      valueFromView = self.textView.text; 
     } else { 
      valueFromView = self.textField.text; 
     } 
     break; 
    case NSInteger16AttributeType: 
    case NSInteger32AttributeType: 
    case NSInteger64AttributeType: 
     valueFromView = [NSNumber numberWithInteger: [self.textField.text integerValue]]; 
     break; 
    case NSDecimalAttributeType: 
    case NSDoubleAttributeType: 
    case NSFloatAttributeType: 
     valueFromView = [NSNumber numberWithDouble: [self.textField.text doubleValue]]; 
     break; 
    case NSBooleanAttributeType: 
     valueFromView = [NSNumber numberWithBool: self.switchControl.isOn]; 
     break; 
    case NSObjectIDAttributeType: 
    case NSTransformableAttributeType: 
    case NSBinaryDataAttributeType: 
    case NSUndefinedAttributeType: 
     NSLog(@"Don't know how to handle attribute type: %d in %s", type, __func__); 
     break; 
    default: 
     NSLog(@"Unrecognized attribute type: %d in %s", type, __func__); 
     break; 
    } 
    [self.delegate managedObjectAttributeEditViewController: self 
      didSaveValue: valueFromView forKey: self.editedFieldKey]; 
} 

ManagedObjectDetailTableViewController가 대리인으로 설정하고 didSaveValue:forKey: 방법은 다음과 같습니다 :

- (void) managedObjectAttributeEditViewController: (ManagedObjectAttributeEditViewController *) controller didSaveValue: (id) value forKey: (NSString *) key { 
    if(value && key) { 
     [self.detailItem setValue: value forKey: key]; 
     NSError *error; 
     if(![self.detailItem.managedObjectContext save: &error]) { 
      // Update to handle the error appropriately. 
      NSLog(@"Unresolved error doing save of attribute %@.\n%@", key, error.localizedDescription); 
     } else { 
      NSLog(@"-- successfully saved"); 
     } 
    } else { 
     NSLog(@"Got a cancel from edit attribute"); 
    } 
    // OK, the attribute editing view controller has told us it is done, pop it 
    [self.navigationController popViewControllerAnimated: YES]; 
} 

그래서, 나는 개체의 목록과 함께 시작하고 경우이 버튼을 터치 저장할 때 실행하는 것입니다 엔터티가 올바르게 정렬됩니다. 행을 만지면 ManagedObjectDetailTableViewController으로 푸시됩니다. 그 속성 행을 건 드리면 ManagedObjectAttributeEditViewController으로 푸시됩니다. 값을 변경하고 을 터치하여을 터치합니다. 이것은 ManagedObjectDetailTableViewController으로 튀어 나와 모든 것이 잘 보입니다. 그런 다음 뒤로 버튼을 터치하여 엔터티의 개체 목록으로 돌아가지만 이제는 더 이상 정렬되지 않습니다 (항상 동일한 순서로 표시되지만 순서에 대한 패턴을 인식하지 못함).

을 저장하고을 저장 한 후 10으로 계산하고 뒤로 버튼을 터치하기 전에 목록이 올바르게 정렬됩니다.

didSaveValue:forKey:에서 [self.detailItem.managedObjectContext save: &error] 메서드 호출을 주석 처리하면 엔터티에 대한 개체 목록이 올바르게 정렬 된 상태로 유지되지만 자동 저장이 발생하기 전에 응용 프로그램을 종료하면 변경 내용이 손실됩니다.

이것은 내가 완료하지 않은 [self.detailItem.managedObjectContext save: &error]과 어떤 관련이 있다고 생각됩니다. 그리고 어떤 이유에서 (동일한 NSManagedObjectContext를 사용하는) 가져온 결과 컨트롤러가 정렬 된 데이터를 검색 할 수 없습니다.

값이 변경되는 속성은 정렬 설명자와 관련이 없으므로 값을 수정하기 전과 후에 표시되는 순서가 동일해야합니다. 데이터베이스가 너무 커서 디스크에 쓰는 데 몇 초가 걸릴 수 있습니다. 시뮬레이터와 장치에서 iOS 5.1의 문제가 나타납니다.

누구도 이와 같은 경험이 있거나 제안이있는 사람이 있습니까?

죄송합니다. 미국의 모든 Stackoverflowers에 대해 7 월 4 일에 너무나 오래되어 행복합니다!


개정 ManagedObjectDetailTableViewController 위임 방법 didSaveValue:forKey: 방법은 다음과 같습니다

- (void) managedObjectAttributeEditViewController: (ManagedObjectAttributeEditViewController *) controller 
      didSaveValue: (id) value forKey: (NSString *) key { 
    if(value && key) { 
     [self.detailItem setValue: value forKey: key]; 
     NSError *error; 
     if(![self.detailItem.managedObjectContext save: &error]) { 
      // Update to handle the error appropriately. 
      NSLog(@"Unresolved error doing save of attribute %@.\n%@", key, error.localizedDescription); 
     } else { 
      NSLog(@"-- successfully saved"); 
      if([self.detailItem.managedObjectContext.parentContext.hasChanges]) { 
       if(![self.detailItem.managedObjectContext.parentContext save: &error]) { 
        NSLog(@"Unresolved error doing save of parent context for attribute %@.\n%@", key, error.localizedDescription); 
       } else { 
        NSLog(@"-- successfully saved the parent context too!"); 
       } 
      } 
     } 
    } else { 
     NSLog(@"Got a cancel from edit attribute"); 
    } 
    // OK, the attribute editing view controller has told us it is done, pop it 
    [self.navigationController popViewControllerAnimated: YES]; 
} 

지금 저장이 두 번 변경이와 있기 때문에 최신 아이폰 OS와 영구 저장소에 그것을 만드는 데 필요한 것을 이해 상위 컨텍스트는 저장 수준이 한 단계 올라간다. 영구 저장 장치에 전달 된 저장을 수행하지 않아도 정렬 순서를 뒤섞어 야하는 이유를 알 수 없습니다. 어쩌면 곳이 마스킹 또는 어쩌면 그것이 작동하는 단지 방법입니다 내 코드에서 다른 버그가 ...이

답변

1

OK, 새로운 스택 추적 등 편집에 따라 : 당신은

을 UIManagedDocument를 사용하여 핵심 데이터 스택을 관리합니다. 즉, 첫 번째 저장은 아마도 UIDocument의 주 스레드 컨텍스트에서 발생하며 두 번째 저장은 백그라운드 컨텍스트에서 발생합니다. UIManagedDocument의 managedObjectContext 컨텍스트의 객체를 사용하고 있음을 확인할 수 있습니까?

또 하나. 어떻게 든 entitySortDescriptorList이 0이되지 않는다는 것을 확인할 수 있습니까 setupFetchedResultsController 방법?

마지막으로, 다른 진단 :

  • 이 최상위 뷰 컨트롤러에서 save:를 호출 시도하고 무슨 일이 일어 나는지.
  • NSFetchedResultsController에 대한 대리인을 만들면 어떻게됩니까? 변경 알림을 받으십니까? 그들은 합리적으로 보입니까?
+0

저장은 주 스레드에 있지만 하나의 관리 대상 개체에 대해 하나의 특성 만 변경했기 때문에 전체 데이터베이스, 한 레코드 만 저장하면 안되며 매우 빨리 저장해야합니다. 'reloadData'는'fetchedResultsController'를 리셋 할 때 발생합니다. 나는 관찰자들을 세우고 내가 배울 수있는 것을 보게 될 것이다. 귀하의 제안에 감사드립니다. – LavaSlider

+0

서로 다른 뷰 컨트롤러 로딩 및 언로드 때문에 알림을 수신 대기하는 중 혼란스러워서 관리 대상 하위 클래스에'willSave'를 추가했습니다. 흥미롭게도 예상대로 내 [self.detailItem.managedObjectContext save : & error]'호출 직후에 호출되지만 나중에 약 10 초 후에 아무 것도하지 않고 다시 호출됩니다. 두 번째 이전에 프로그램을 종료하면 다음 번에 응용 프로그램을 실행할 때 데이터베이스에 변경 사항이 없습니다! – LavaSlider

+0

두 번째 알림의 스택 추적을 보거나 게시하여 어디에서 왔는지 파악할 수 있습니다. –

관련 문제