21

我有一个包含内容的数组。像往常一样,它包含 20 个对象。我希望在 Tableview 中将相同的数组分成 2 个部分。我正在尝试在当前数组中使用 NSMake 来实现它。例如,我需要在第一个 tableview 部分中获取 3 行,第二个将包含所有其余部分(17 行)。

switch (section) {
        case 0:
            return
            [[array subarrayWithRange:NSMakeRange(3, 8)] count];
            // in this line, it always takes from the first object in array, despite I told hime start from 3 (If I understand right, how to works NSMakeRange)
            break;
        case 1:
            return
            [[array subarrayWithRange:NSMakeRange(9, 19)] count];
            // here my app is crashing with an error 
            //*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray subarrayWithRange:]: range {9, 19} extends beyond bounds [0 .. 19]'
        default:
            break;
    }

有人可以帮我吗?

4

3 回答 3

62

NSMakeRange定义为(startingIndex, length),而不是(start, end)您尝试使用它的方式。

因此,如果您需要前 3 个对象,那么其余的对象将如下所示:

switch (section) {
    case 0:
        // This returns objects 0-2 in the array
        return [array subarrayWithRange:NSMakeRange(0, 3)];
    case 1:
        // This returns objects 3-20 in the array
        return [array subarrayWithRange:NSMakeRange(3, 17)];
    default:
        break;
}

编辑:根据您的评论,您实际上是在寻找以部分行数返回的计数。由于您使用的是固定数量的行,因此您可以在 case 语句中返回实际数量。

switch (section) {
    case 0:
        // This returns the count for objects 0-2 in the array
        return 3;
    case 1:
        // This returns the count for objects 3-20 in the array
        return 17;
    default:
        break;
}

您实际上并不需要使用[subarrayWithRange], 也不NSMakeRange。如果您确实需要在某些时候引用实际的数组,您将获得一个 NSIndexPath 对象,您可以使用它从您的数组中获取对象。您将需要使用 section 和 row 属性。

编辑:NSRange->NSMakeRange

于 2013-10-25T18:31:48.480 回答
5

正如其他人所指出的那样,您使用NSRange不当。

它的定义是

typedef struct _NSRange {
      NSUInteger location;
      NSUInteger length;
} NSRange;

所以结构的第二个参数是范围的长度,而不是你显然认为的最后一个元素的位置。


话虽如此,你正在做的事情比它应该做的要复杂得多。

生成已知长度的子数组然后返回子数组本身的长度的目的是什么?考虑到这一点:

return [[array subarrayWithRange:NSMakeRange(3, 8)] count];

应该是(NSRange正确使用)

return [[array subarrayWithRange:NSMakeRange(3, 6)] count];

但实际上可能只是

return 6;

或者如果范围长度是一个参数

return length;

同样,世界上没有必要对数组进行切片和计数。长度是先验已知的。


所以在上下文中UITableViewDataSource,你必须

  • 返回 中每个部分的计数-tableView:numberOfRowsInSection:。就像是

    switch(section) {
        case 0: return 2;
        case 1: return 18;
    }    
    
  • 返回中的实际对象tableView:cellForRowAtIndexPath:。就像是

    id object = nil;
    switch (indexPath.section) {
        case 0:
            object = self.objects[indexPath.row];
            break;
        case 1:
            object = self.objects[2 + indexPath.row];
            break;
    }
    ...
    

作为一个额外的提示,我建议使用不同的符号来构建结构

NSMakeRange(0, 42)

可以写

(NSRange){ .location = 0, .length = 42 }

这更具可读性(并且更不容易出错,尤其是当您对参数的含义有疑问时)。

甚至

(NSRange){ 0, 42 }

是可以接受的。我认为它比 更好(并且更短)NSMakeRange,但它失去了好处或可读性。

于 2013-10-25T19:42:08.503 回答
1

好的,我已经解决了我的问题

在我的 Fetcher 课上,我做到了

_sectionOne = [news objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 3)]];
_sectionTwo = [news objectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(3, 17)]];

然后

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 2;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    switch (section) {
        case 0:
            return [_sectionOne count];
            break;
        case 1:
            return [_sectionTwo count];
            break;
        default:
            break;
    }
    return 0;
}

然后在方法 cellForRowAtIndexPath 中:

 switch (indexPath.section) {
        case 0:
            item = [_sectionOne objectAtIndex:indexPath.row];
            break;
        case 1:
            item = [_sectionTwo objectAtIndex:indexPath.row];
            break;
        default:
            break;
    }

item - 这是我的带有 MVC 的 NSObject

所以它按我的意愿工作:)

感谢所有试图帮助我的人。

干杯

于 2013-10-27T20:12:39.357 回答