Создание массива для cellForRowAtIndexPath с помощью других методов

#ios #objective-c #arrays #uitableview

#iOS #objective-c #массивы #uitableview

Вопрос:

У меня есть индексированный tableView файл, который отображает список песен из библиотеки iPod пользователя. Вот как я в настоящее время получаю названия песен, что приводит к очень медленной прокрутке:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.textLabel.text= [self titleForRow:indexPath];  //getting cell content
}
  

…который вызывает эти методы:

 -(NSString *)titleForRow:(NSIndexPath *)indexpath{

    NSMutableArray* rowArray=[[NSMutableArray alloc]initWithCapacity:0];
    rowArray=[self getArrayOfRowsForSection:indexpath.section];
    NSString *titleToBeDisplayed=[rowArray objectAtIndex:indexpath.row];
    return titleToBeDisplayed;

}

-(NSMutableArray *)getArrayOfRowsForSection:(NSInteger)section
{
    NSString *rowTitle;
    NSString *sectionTitle;
    NSMutableArray *rowContainer=[[NSMutableArray alloc]initWithCapacity:0];

    for (int i=0; i<self.alphabetArray.count; i  )
    {
        if (section==i)   // check for right section
        {
            sectionTitle= [self.alphabetArray objectAtIndex:i];  //getting section title
            for (MPMediaItem *song in songs)
            {
                NSString *title = [song valueForProperty:MPMediaItemPropertyTitle];
                rowTitle= [title substringToIndex:1];  //modifying the statement to its first alphabet
                if ([rowTitle isEqualToString:sectionTitle])  //checking if modified statement is same as section title
                {
                    [rowContainer addObject:title];  //adding the row contents of a particular section in array
                }
            }
        }
    }
    return rowContainer;
}
  

Проблема в том, что для каждого cellForRowAtIndexPath я вызываю эти методы и создаю эти массивы для каждой ячейки. Итак, мне нужно создать отдельный массив и просто вызвать objectAtIndex из этого массива.

Это то, что я пробовал до сих пор: создал NSMutableArray *newArray , и следующий метод:

 -(NSMutableArray *)getNewArray:(NSInteger)section
{
    NSString *rowTitle;
    NSString *sectionTitle;

    for (int i=0; i<self.alphabetArray.count; i  )
    {
        if (section==i)   // check for right section
        {
            sectionTitle= [self.alphabetArray objectAtIndex:i];  //getting section title
            for (MPMediaItem *song in songs)
            {
                NSString *title = [song valueForProperty:MPMediaItemPropertyTitle];
                rowTitle= [title substringToIndex:1];  //modifying the statement to its first alphabet
                if ([rowTitle isEqualToString:sectionTitle])  //checking if modified statement is same as section title
                {
                    [newArray addObject:title];  //adding the row contents of a particular section in array
                }
            }
        }
    }
    return newArray;
}
  

Но это кажется очень неправильным, и я действительно не понимаю, как это решить. Я понятия не имею, как создать отдельный массив с помощью этих методов, newArray заполнив его названиями песен, и я уже довольно долго искал в Google и не могу найти ничего, что могло бы мне помочь.

Может ли кто-нибудь указать мне правильное направление или, пожалуйста, покажите мне, как я создаю newArray? Я прикрепил сюда свой источник данных TableView. Спасибо. Любая помощь будет высоко оценена.

Комментарии:

1. Можете ли вы добавить, как выглядит ваш источник данных (ваш алфавитный массив). У вас есть много кода, который выглядит так, как будто он выполняет поиск в вашем источнике данных и создает новый источник данных, и все это для того, чтобы вы могли создать ячейку. Очистка этого очень помогла бы.

Ответ №1:

Ячейки табличного представления последовательно ставятся в очередь и удаляются из очереди. Используя эту возможность, вы должны ожидать, что только разделы изменяются с меньшей частотой. Вы можете использовать статические переменные, чтобы исключить выборку раздела. Посмотрите на мой код

 -(NSString *)titleForRow:(NSIndexPath *)indexpath{
    static NSIndexPath *funIndexPath;
    static NSMutableArray *funSectionArray;
    if (!funIndexPath || funIdexpath.section != indexpath.section) {
        funIndexPath = indexpath;
        funSectionArray = [self getArrayOfRowsForSection:indexpath.section];
    }
    rowArray = funSectionArray;
    NSString *titleToBeDisplayed = [rowArray objectAtIndex:indexpath.row];
    return titleToBeDisplayed;
}
  

Это первая возможная оптимизация.

Когда я смотрю на ваш массив результатов выборки, некоторые вещи не ясны. Почему вы повторяете проверку section == i . Вы можете просто заменить section i в своем коде.

 -(NSMutableArray *)getNewArray:(NSInteger)section {
    NSString *rowTitle;
    NSString *sectionTitle;

    sectionTitle = [self.alphabetArray objectAtIndex:section];  //getting section title
        for (MPMediaItem *song in songs) {
            NSString *title = [song valueForProperty:MPMediaItemPropertyTitle];
            rowTitle= [title substringToIndex:1];  //modifying the statement to its first alphabet
            if ([rowTitle isEqualToString:sectionTitle])  //checking if modified statement is same as section title
            {
                [newArray addObject:title];  //adding the row contents of a particular section in array
            }
        }
    return newArray;
}
  

До сих пор не ясно, чего вы пытаетесь достичь здесь.

Идя вразрез с моим собственным ответом, я предлагаю вам не вычислять данные для отображения во время просмотра. время рендеринга. Вам нужно создавать ячейки как можно быстрее. Почему бы не создать свойство или iVar (как предлагает @bauerMusic) и вычислить дату в viewDidLoad или объявить пользовательскую функцию, которая перезагрузит ваше свойство (возможно Array , or Dictionary ) и при рендеринге пользовательского интерфейса просто установите значения (в вас viewForIndexPath )?

Вы можете использовать массив двухуровневой глубины для хранения разделов и строк. т.Е. Уровень 1 — Разделы и массив строк, уровень 2 — строка.

Комментарии:

1. Спасибо, что помогли мне. В getNewArray я пытался создать новый массив со всеми названиями моих песен, чтобы я мог загрузить его только один раз, а затем просто обратиться к одному массиву cellForRow . Прошу прощения за неясность. Поскольку я прокомментировал ответы Hot Licks и bauerMusic, я не понимаю, как создавать и добавлять названия песен в @property NSMutableDictionary с помощью этих методов. :S

Ответ №2:

В центре всего этого:

 cell.textLabel.text = [self titleForRow:indexPath];
  

Теперь, что вы на самом деле используете NSString . Просто. Вместо этого вы создаете новый массив для каждой ячейки при каждом вызове??
Почему бы не иметь один массив, скажем, NSMutableArray. Используйте его как @property или локальный iVar.

 @property (strong, nonatomic) NSMutableArray *rowArray;


// Instantiate in -viewDidLoad
rowArray = [NSMutableArray array]; // Much more elegant IMHO
  

Теперь вызовите метод, который выполняет всю загрузку содержимого, но сделайте это ОДИН РАЗ. Вы всегда можете вызвать его снова для обновления.

Что-то вроде:

 // In -viewDidLoad
rowArray = [NSMutableArray array];

[self loadArrayContent];
  

Тогда вы cellForRowAtIndexPath должны использовать только предварительно rowArray загруженные и просто извлекать NSString из него заголовки.

Комментарии:

1. Спасибо за ваш ответ, глядя на ответ Hot Licks, возможно, мне следует добавить эту информацию в @property NSMutableDictionary . Как бы мне это сделать? На самом деле это был мой первоначальный вопрос, но я был определенно неясен (прошу прощения). Я попытался добавить все названия песен в свой getNewArray метод, но это с треском провалилось. Как мне добавить все заголовки в a @property NSMutableDictionary с помощью этих методов, чтобы сохранить мою индексацию? :S

2. Есть некоторые концептуальные различия, но важно отметить, что вам все еще нужен an Array , только этот массив находится в an NSDictionary . Существует буквальный ярлык @{@"key":@"value"} , в противном случае используйте setObject:forKey: . Пример: [myDictionary setObject:myArray forKey:@"Song List"]; вот полная ссылка: developer.apple.com/library/mac/documentation/Cocoa/Reference /…

Ответ №3:

Мой общий способ обработки табличного представления — создать (во время настройки табличного представления) NSMutableArray для строк (привязанных к объекту источника данных). Каждая запись в массиве представляет собой NSMutableDictionary, который «заполнен» базовым материалом для строки, и если для отображения строки требуется дополнительная информация, она кэшируется в словаре. (Там, где есть несколько разделов, я использую массив разделов, содержащих массивы строк.)

Что я мог бы сделать для списка воспроизведения, так это инициализировать массив пустыми словарями, затем, по мере прокрутки, получить доступ к каждому элементу списка воспроизведения и кэшировать его в словаре.

На самом деле, если бы кто-то действительно захотел, обновление словаря можно было бы выполнить с помощью фоновой задачи (с соответствующей блокировкой), чтобы операции поиска не препятствовали скорости прокрутки.

Комментарии:

1. Спасибо за ваш ответ, мой первоначальный вопрос был немного неясным, поскольку я спрашивал, как на самом деле добавить все заголовки в новый массив, поскольку я пытался сделать это getNewArray в своей OP, но все пошло ужасно неправильно. Как бы я добавил все названия песен в an @property NSMutableDictionary с помощью этих методов. :S

2. @user3127576 — Создайте NSMutableArray. Заполните его либо объектами NSMutableDictionary (как я предлагал выше), либо объектами NSNull (обычная версия), чтобы иметь правильный размер. Обновляйте массив по мере ссылки на каждую строку. Легко проверить, был ли данный элемент массива уже обновлен.