Как создать подрамник NSArray с помощью NSRange?
У меня есть массив с контентом. как обычно, он содержит 20 объектов. Я хочу, чтобы один и тот же массив разбился на 2 раздела в Tableview.
Я пытаюсь реализовать его с помощью NSMake в текущем массиве. Например, мне нужно попасть в первый раздел 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;
}
Кто-нибудь может мне помочь?
Ответы
Ответ 1
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, который вы можете использовать для получения объекта из вашего массива. Вам нужно будет использовать свойства раздела и строки.
Изменить: NSRange
→ NSMakeRange
Ответ 2
Как уже отмечалось, вы используете 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
, но оно теряет преимущества или удобочитаемость.
Ответ 3
Хорошо, я решил свою проблему
В моем классе 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 - это мой NSObject с MVC
So It working Как я и хотел:)
Спасибо, что все пытались мне помочь.
Приветствия