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

Ant*_*ton 21 arrays objective-c nsarray ios nsrange

我有一个包含内容的数组.像往常一样,它包含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;
    }
Run Code Online (Sandbox Code Playgroud)

有人可以帮我吗?

Joe*_*her 57

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;
}
Run Code Online (Sandbox Code Playgroud)

编辑:根据您的评论,您实际上是在寻找计数以返回部分中的行数.由于您使用的是固定数量的行,因此您只需返回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;
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:NSRange- >NSMakeRange


Gab*_*lla 5

正如其他人已经注意到你使用NSRange不当.

它的定义是

typedef struct _NSRange {
      NSUInteger location;
      NSUInteger length;
} NSRange;
Run Code Online (Sandbox Code Playgroud)

所以struct的第二个参数是范围的长度,而不是你明显想到的最后一个元素的位置.


话虽这么说,你正在做的事情要比它应该复杂得多.

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

return [[array subarrayWithRange:NSMakeRange(3, 8)] count];
Run Code Online (Sandbox Code Playgroud)

应该(NSRange正确使用)

return [[array subarrayWithRange:NSMakeRange(3, 6)] count];
Run Code Online (Sandbox Code Playgroud)

但它实际上可能只是

return 6;
Run Code Online (Sandbox Code Playgroud)

或者如果范围长度是参数

return length;
Run Code Online (Sandbox Code Playgroud)

同样,世界上没有必要切片和计数.长度是先验已知的.


所以在UITableViewDataSource你必须的背景下

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

    switch(section) {
        case 0: return 2;
        case 1: return 18;
    }    
    
    Run Code Online (Sandbox Code Playgroud)
  • 返回实际的对象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;
    }
    ...
    
    Run Code Online (Sandbox Code Playgroud)

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

NSMakeRange(0, 42)
Run Code Online (Sandbox Code Playgroud)

可以写

(NSRange){ .location = 0, .length = 42 }
Run Code Online (Sandbox Code Playgroud)

它更易读(并且更不容易出错,特别是当您对参数的含义有疑问时).

甚至

(NSRange){ 0, 42 }
Run Code Online (Sandbox Code Playgroud)

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