如何使用NSRange创建NSArray的子​​阵列?

时间:2013-10-25 18:29:38

标签: ios objective-c nsarray nsrange arrays

我有一个包含内容的数组。像往常一样,它包含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;
    }

有人可以帮我吗?

3 个答案:

答案 0 :(得分:56)

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

答案 1 :(得分:5)

其他人已经注意到您使用NSRange不正确。

它的定义是

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

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


话虽这么说,你正在做的事情要比现在复杂得多。

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

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更好(也更短),但它失去了好处或可读性。

答案 2 :(得分: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

所以它的工作正如我所愿:)

感谢所有人帮助我。

干杯