Подтвердить что ты не робот

Как создать подрамник 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;
    }

Кто-нибудь может мне помочь?

4b9b3361

Ответ 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, который вы можете использовать для получения объекта из вашего массива. Вам нужно будет использовать свойства раздела и строки.

Изменить: NSRangeNSMakeRange

Ответ 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 Как я и хотел:)

Спасибо, что все пытались мне помочь.

Приветствия