#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
с помощью этих методов, чтобы сохранить мою индексацию? :S2. Есть некоторые концептуальные различия, но важно отметить, что вам все еще нужен an
Array
, только этот массив находится в anNSDictionary
. Существует буквальный ярлык@{@"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
с помощью этих методов. :S2. @user3127576 — Создайте NSMutableArray. Заполните его либо объектами NSMutableDictionary (как я предлагал выше), либо объектами NSNull (обычная версия), чтобы иметь правильный размер. Обновляйте массив по мере ссылки на каждую строку. Легко проверить, был ли данный элемент массива уже обновлен.