代码之家  ›  专栏  ›  技术社区  ›  Steve Weller

重新获取nsfetchedresultsController有什么作用吗?

  •  2
  • Steve Weller  · 技术社区  · 16 年前

    我有一个获取的结果控制器,它在我的Thing实体上有一个谓词,如下所示:“ThingDomain.DomainCurrentAccount!=“空”。它会查找当前域中的所有“我的东西”对象。当前域由帐户实体和其中一个域实体之间的一对一关系定义。每样东西都属于一个领域,每个领域都有很多东西。除一个域以外的所有域都与帐户具有空关系。

    这很有效,我的桌面视图很满意。

    稍后,我通过修改与帐户的关系来更改当前域。我向现在是当前域的域添加了更多的内容,因为它们满足谓词,所以它们被添加到TableView中。然而,现在属于非当前域的内容仍然保留在TableView中,即使它们不再满足谓词。

    我试过重新提取,但没有效果,所以我对再次提取实际上做了什么感到困惑。它是否根据实体重新评估谓词?

    我在更改当前域之前删除了当前域中的所有内容,从而解决了这个问题,但是我觉得不必这样做。

    1 回复  |  直到 16 年前
        1
  •  4
  •   gerry3    16 年前

    再次执行提取后是否重新加载了表视图?

    这对我很有用:

    self.fetchedResultsController = nil;
    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) {
        NSLog(@"Error in refetch: %@",[error localizedDescription]);
        abort();
    }
    
    [self.tableView reloadData];
    

    更新
    获取的结果控制器正在观察对象的变化,而不是域对象。由于我们正在更改域对象上的帐户,所以获取的结果控制器没有更新(除了新的内容)是有意义的。
    理想的解决方案是告诉托管对象上下文或获取的结果控制器哪些确切的事情已经“改变”(循环处理以前拥有帐户的域中的事情),但这仍然是一个手动过程。
    另一种方法是再次执行FETCH并重新加载为我工作的表。

    我根据你的描述创建了这个模型:

    帐户---域---事情

    为了测试这一点,我在域1中创建了“1”和“2”,在域2中创建了“3”、“4”和“5”。域一拥有帐户,而域二没有帐户。
    当应用程序加载时,表视图按预期显示“1”和“2”。
    当我点击“更改”时,域2被分配帐户,域1失去其帐户。另外,在域2中创建了一个名为“six”的新东西。
    “6”和“1”和“2”一起出现,即使它们不再满足谓词。这与您描述的问题相匹配。
    然后,我点击“refetch”,表格会重新加载“3”、“4”、“5”和“6”。这是所期望的行为。

    以下是相关的视图控制器代码:

    - (void)addTestData {
        account = [NSEntityDescription insertNewObjectForEntityForName:@"Account" inManagedObjectContext:self.managedObjectContext];
        domainOne = [NSEntityDescription insertNewObjectForEntityForName:@"Domain" inManagedObjectContext:self.managedObjectContext];
        domainTwo = [NSEntityDescription insertNewObjectForEntityForName:@"Domain" inManagedObjectContext:self.managedObjectContext];
        [domainOne setValue:account forKey:@"domainCurrentAccount"];
    
        NSArray *thingNames = [NSArray arrayWithObjects:@"One", @"Two", @"Three", @"Four", @"Five", nil];   
        for (NSString *name in thingNames) {
            NSManagedObject *thing = [NSEntityDescription insertNewObjectForEntityForName:@"Thing" inManagedObjectContext:self.managedObjectContext];
            [thing setValue:name forKey:@"thingName"];
            if (name == @"One" || name == @"Two") {
                [thing setValue:domainOne forKey:@"thingDomain"];
            } else {
                [thing setValue:domainTwo forKey:@"thingDomain"];
            }
        }
    }
    
    - (void)change {
        [domainTwo setValue:account forKey:@"domainCurrentAccount"];
        [domainOne setValue:nil forKey:@"domainCurrentAccount"];
        NSManagedObject *thing = [NSEntityDescription insertNewObjectForEntityForName:@"Thing" inManagedObjectContext:self.managedObjectContext];
        [thing setValue:@"Six" forKey:@"thingName"];
        [thing setValue:domainTwo forKey:@"thingDomain"];
    }
    
    - (void)refetch {
        self.fetchedResultsController = nil;
        NSError *error = nil;
        if (![self.fetchedResultsController performFetch:&error]) {
            NSLog(@"Error in refetch: %@",[error localizedDescription]);
            abort();
        }
    
        [self.tableView reloadData];
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        UIBarButtonItem *changeButton = [[UIBarButtonItem alloc] initWithTitle:@"Change" style:UIBarButtonItemStyleBordered target:self action:@selector(change)];
        self.navigationItem.leftBarButtonItem = changeButton;
        [changeButton release];
    
        UIBarButtonItem *refetchButton = [[UIBarButtonItem alloc] initWithTitle:@"Refetch" style:UIBarButtonItemStyleBordered target:self action:@selector(refetch)];
        self.navigationItem.rightBarButtonItem = refetchButton;
        [refetchButton release];
    
        [self addTestData];
    
        NSError *error = nil;
        if (![[self fetchedResultsController] performFetch:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
    
    推荐文章