1

在我的甜蜜应用程序中,您可以使用项目列表中的两种项目。有可装备的物品和袋子物品。当您导航到清单屏幕时,表格视图有两个部分,每个部分有 4 个单元格。四个单元格用于装备物品,四个单元格用于“包”中的物品。如果您没有任何装备,则单元格只会说“空”。

如何根据结果对象的形状有条件地填充表格单元格?

这是我希望拥有的代码:

- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {

  static NSString *CellIdentifier = @"Cell";

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  }

  // this returns 'nil' if the index path was out of bounds
  NSManagedObject * item = [self.fetchedResultsController carefullyGetObjectAtIndexPath:indexPath];

  if (nil == item) {
    cell.textLabel.text = @"empty"; 

  } else {
    cell.textLabel.text = [item valueForKey:@"name"];

  }

} 

我在尝试实现这个“小心”的 objectAtIndexPath 时遇到了一些问题:

我尝试了边界检查,但我遇到了麻烦,因为 fetchedArray 是扁平的,而我试图导航的概念模型不是扁平的:行是“in”部分。

我尝试使用 try/catch,但后来我记得越界元素是未定义的,而不是 nil ... . 我现在的设置:

@try {

  NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];

  return managedObject;
}
@catch (NSException * e) {
  return nil;
}

始终给我 5 个条目,4 个在正确的位置和 1 个奇数球,这是从另一部分重复的。

不确定如何手动导航获取的结果。我正在玩四个项目,每种两个。我曾希望它像双重嵌套数组一样简单,部分在外面,行在里面。似乎事情比这更棘手。当我检查 fetchedResults NSArray 时,我发现它是平的。所有的“包”物品都是第一位的,然后是“装备”。不过,我不认为我可以依赖这种排序,所以我觉得制作一个从 indexPath 部分到数组索引的映射函数并不安全。(我可以确信对此感到安全)。

我想到的另一种选择是在我的库存中填充 8 个“空”项目,当这些部分没有完全填满时,这些项目将作为占位符结果返回。但这并不适合我。

我意识到为什么这不起作用:表不应该有“空”行。但我希望我的表有空行!

更新

这是我现在使用的方法...

- (NSManagedObject*) carefullyGetObjectAtIndexPath:(NSIndexPath*)indexPath 
{
  NSLog(@"in %@ %s", [self class], _cmd);

  NSString * desiredType = (indexPath.section == BAG_SECTION)? @"bag" : @"equipable";
  NSArray * fetchedObjects = [self.fetchedResultsController fetchedObjects];
  NSInteger sectionStartIndex = -1;

  // iterate until you hit a type you like
  NSUInteger i, count = [fetchedObjects count];
  for (i = 0; i < count; i++) {
    NSObject * obj = [fetchedObjects objectAtIndex:i];
    NSString * fetchedType = (NSString*)[obj valueForKey:@"type"];

    if ([desiredType isEqualToString:fetchedType]) {
      sectionStartIndex = i;
      break;
    }
  }

  if (-1 == sectionStartIndex) {
    // maybe there aren't any of that type of item

  } else {

    NSInteger calculatedEntityIndex = sectionStartIndex + indexPath.row;
    NSLog(@"calculated index %d", calculatedEntityIndex);

    // if we are still in the array
    if (calculatedEntityIndex < [fetchedObjects count]) {

      // then we can get the object
      NSManagedObject * entity = [fetchedObjects objectAtIndex:calculatedEntityIndex];

      // and if we are still in the right section
      NSString * typeForEntityAtIndex = [entity valueForKey:@"type"];

      if ([desiredType isEqualToString:typeForEntityAtIndex]) {
        // then this is what we wanted

        return entity;
      }
    }
  }

  return nil;   
}

我真的不觉得我应该迭代这样的事情......

z。

全面披露:这是一个长期项目,但该项目是通过任何必要的方式制作应用程序。这包括第三方库、在 stackoverflow 上提问等等……这个学期项目的目标是体验在更大的东西上工作,比如一个甜蜜的应用程序,而不是学习 Objective-c。

4

1 回答 1

1

齐吉,

NSFetchedResultsController很多限制。如果您不能使您的架构满足其严格的要求,并且您可能没有,那么您应该构建您tableView的多个NSFetchRequests. 这很简单。大多数有趣tableView的 s 就是这样做的。当您执行较大的提取然后使用集合类上的集合和过滤操作细化搜索时,Core Data 确实工作得最好。

tableViews 可以有空行。您只需要将其与各种委托和单元配置代码中的自定义代码进行协调。

你有很多选择来解决你的问题。看来您对非常有限的框架 API 不满意。你是一个初出茅庐的程序员。自己滚。

安德鲁

PS 你有一个奇怪的目标,即编写一个 Mac OS X/iOS 应用程序而不需要学习 Objective-C。您实际上已经选择了框架中的一项技术,即 Core Data,它可以最大限度地发挥 Objective-C 的能力。(在我看来,作为 iOS 程序员的教育者,学习一个非常不同的持久性模型(Core Data 的模型)的复杂性可能会比退缩到平凡的主流 SQL 解决方案更好。)如果你更喜欢使用不同的语言,MacRuby/RubyMotion 相当有效。

于 2012-07-01T15:03:33.660 回答