【问题标题】:Error when trying to get value of an entity attribute尝试获取实体属性的值时出错
【发布时间】:2015-08-04 00:21:38
【问题描述】:

我正在尝试从实体属性中获取值:

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.mapaView setDelegate:self];


    MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
    request.naturalLanguageQuery = self.loja.endereco; // <-- Here
    request.region = self.mapaView.region;

    MKLocalSearch *search = [[MKLocalSearch alloc] initWithRequest:request];

    [search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error)
    {
        NSMutableArray *placemarks = [NSMutableArray array];
        for (MKMapItem *item in response.mapItems) {
            [placemarks addObject:item.placemark];
        }
        [self.mapaView removeAnnotations:[self.mapaView annotations]];
        [self.mapaView showAnnotations:placemarks animated:NO];
    }];
}

但我收到此错误:

2015-08-03 21:01:41.196 MinhaBrasilia[2465:69970] -[__NSCFDictionary endereco]: unrecognized selector sent to instance 0x7fb2faed1910
2015-08-03 21:01:41.199 MinhaBrasilia[2465:69970] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary endereco]: unrecognized selector sent to instance 0x7fb2faed1910'

Loja (self.loja) 是一个实体,它是从 plist 创建的,使用 NSPredicate 过滤,通过方法 tableView:cellForRowAtIndexPath 加载并通过 prepareForSegue:sender 作为参数传递,所有这些都在上一个屏幕中。

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     LojaTableViewCell *celula = [tableView dequeueReusableCellWithIdentifier:IdentificadorCelula
                                                                forIndexPath:indexPath];

     self.listaFiltrada = [self carregarPlistDeLojasComId:identificadorBtn filtradaPor:self.txtCategoria];

     self.loja = [NSEntityDescription insertNewObjectForEntityForName:@"Loja" inManagedObjectContext:self.managedObjectContext];

     [self.loja setValue:[[self.listaFiltrada objectAtIndex:indexPath.row] objectForKey:@"titulo"] forKey:@"titulo"];
     [self.loja setValue:[[self.listaFiltrada objectAtIndex:indexPath.row] objectForKey:@"subtitulo"] forKey:@"subtitulo"];
     [self.loja setValue:nil forKey:@"categoria"]; //Not implemented
     [self.loja setValue:[[self.listaFiltrada objectAtIndex:indexPath.row] objectForKey:@"endereco"] forKey:@"endereco"];
     [self.loja setValue:nil forKey:@"quadra"]; //Not implemented
     [self.loja setValue:[[self.listaFiltrada objectAtIndex:indexPath.row]  objectForKey:@"telefone"] forKey:@"telefone"];


     [celula preencherCelulaComTitulo:self.loja.titulo
                         comSubtitulo:self.loja.subtitulo
                         comCategoria:self.loja.categoria
                          comEndereco:self.loja.endereco
                            comQuadra:self.loja.quadra
                          comTelefone:self.loja.telefone];

    [celula setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
     return celula;
 }

- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    self.loja = [self.listaFiltrada objectAtIndex:indexPath.row];
    [self performSegueWithIdentifier:SegueLoja sender:self.loja];
}

#pragma mark - Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if([segue.identifier isEqualToString:SegueLoja]) {
        DetalheViewController *detalheVC = (DetalheViewController *)[[segue destinationViewController] topViewController];
        [detalheVC setLoja:sender];
    }
}

显然我得到了一本字典,如果我这样做request.naturalLanguageQuery = [self.loja valueForKey:@"endereco"];,我可以获得我想要的属性,但这样我相信我没有使用CoreData的资源。

【问题讨论】:

  • endereco 看起来像是NSDictionary 的密钥...您尝试使用request.naturalLanguageQuery = self.loja[@"endereco"]; 吗?或者...request.naturalLanguageQuery = [self.loja objectForKey:@"endereco"];?
  • 我还没有尝试过那种方式。我认为做self.entity.attribute 会起作用,考虑到实体已被收费并且属性已被填充。即使这样[self.entity valueForKey: @ "attribute"]; 是使用CoreData 的“正确方式”?

标签: ios objective-c cocoa core-data


【解决方案1】:

你得到的错误是因为self.loja 是一个字典:在didSelectRowAtIndexPath 你有:

self.loja = [self.listaFiltrada objectAtIndex:indexPath.row];

这是从您过滤的 plist 派生的 NSDictionary,而不是您在 cellForRowAtIndexPath 中创建的 NSManagedObject。字典没有实现endereco 方法,因此出现错误。它确实实现了valueForKey,所以它会起作用:但如果你遵循这条路线,你访问的是字典的键,而不是 NSManagedObject。

我认为您应该重新考虑您的方法 - 使用 cellForRowAtIndexPath 将 plist 处理为 NSManagedObjects 是一个坏主意。它只会为可见单元格调用,并且可能会为同一行调用多次(如果它在屏幕上和屏幕外滚动)。我会编写一个例程将所有 plist 处理为 Core Data,并生成一个 NSManagedObjects 数组,然后您可以将其用作表格视图的数据源。

【讨论】:

  • 是的,这正是我在考虑使用CoreData,但我不知道如何实现。你说创建一个方法来读取 plist 并返回 NSManagedObject。因此,在方法 cellForRowAtIndexPath 中获取此方法,该方法将 NSManagedObject 作为数据返回以填充单元格。
  • 读取您的 plist 并将其转换为 CoreData 将是永久性的;这是一次操作(除非 plist 更改?)。因此,您可以向您的 App Delegate 添加一个方法来执行此操作。然后在表视图的viewDidLoad 中,您可以将所有 NSManagedObjects 提取到一个数组中(您可以包含一个谓词来过滤它们以匹配txtCategoria)。然后在cellForRowAtIndexPath 中使用该数组。或者你可以使用NSFetchedResultsController 来获取对象。
  • plist 文件不会改变。我可以创建自己的方法还是需要在didFinishLaunchingWithOptions 方法中进行转换?通过这样做,当我将 NSManagedObjects 获取到一个数组时,我不会落入我当前使用的相同概念,对吧?
  • 我会添加您自己的方法来将 plist 加载到 CoreData 中,并从 didFinishLaunchingWithOptions: 调用它。然后在您的表格视图控制器中,您根本不需要参考 plist;您可以只获取 NSManagedObjects - 这应该可以避免您遇到的特定错误,但也可以为表格视图提供强大的数据源。
猜你喜欢
  • 1970-01-01
  • 2021-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-04
相关资源
最近更新 更多