Отправлено 25 Июль 2012 - 16:03
Нереально лагает табличка, делал делал вот по этому уроку.
Не знаю в чем дело, единственное, я массивы собираю на стороне из SQLite, возможно в этом дело?
Полный код класса: .h, .m
Не знаю в чем дело, единственное, я массивы собираю на стороне из SQLite, возможно в этом дело?
// Table
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[self.refreshProtocol returnDataForTable] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSArray *curent = [self curent:section];
return [curent count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[[self.refreshProtocol returnDataForTable] allKeys] objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
}
NSArray *curent = [self curent:indexPath.section];
cell.textLabel.text = [curent objectAtIndex:indexPath.row];
return cell;
}
- (NSArray *)curent:(NSInteger)index {
NSArray *keys = [[self.refreshProtocol returnDataForTable] allKeys];
NSString *curentKey = [keys objectAtIndex:index];
NSArray *curent = [[self.refreshProtocol returnDataForTable] objectForKey:curentKey];
return curent;
}
Полный код класса: .h, .m
#2
Отправлено 25 Июль 2012 - 18:43
Да что-то слишком много call-ов, долго строится ячейка. Таблица не все ячейки сразу строит а по мере скрола (чтобы память не забивать), те что "за экраном" дестроит и строит по новой когда до них доскролишь.
Поэтому этот метод лучше не нагружать.
есть пара вариантов
1. сформируйте сначала массив данных и из него заполняйте таблицу
2. если не большая таблица, можно сразу сформировать массив ячеек (но они все в памяти будут соответствено)
Поэтому этот метод лучше не нагружать.
есть пара вариантов
1. сформируйте сначала массив данных и из него заполняйте таблицу
2. если не большая таблица, можно сразу сформировать массив ячеек (но они все в памяти будут соответствено)
#3
Отправлено 25 Июль 2012 - 19:55
Nikitich (25 Июль 2012 - 18:43) писал:
1. сформируйте сначала массив данных и из него заполняйте таблицу
Я пробовал передавать словарь с данными, прописал в @interface, присвоил в viewDidLoad, но приложение стало вылетать при попытке загрузить еще ячейки
// Table
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [tableData count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSArray *curent = [self curent:section];
return [curent count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[tableData allKeys] objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
}
NSArray *curent = [self curent:indexPath.section];
cell.textLabel.text = [curent objectAtIndex:indexPath.row];
return cell;
}
- (NSArray *)curent:(NSInteger)index {
NSArray *keys = [tableData allKeys];
NSString *curentKey = [keys objectAtIndex:index];
NSArray *curent = [tableData objectForKey:curentKey];
return curent;
}
Насколько я могу судить, оно стопорится на:
NSArray *curent = [self curent:indexPath.section];
Nikitich (25 Июль 2012 - 18:43) писал:
2. если не большая таблица, можно сразу сформировать массив ячеек (но они все в памяти будут соответствено)
А не расскажете, как такое реализовывается?
#4
Отправлено 25 Июль 2012 - 20:39
Цитата
Я попробовал один раз передавать словарь с данными, прописал в @interface, присвоил в viewDidLoad, но приложение стало вылетать при попытке загрузить еще ячейки (код ниже)
Значит вы его не проиниализировали myArray = [[NSArray alloc] initWithArray:..]; а просто присвоили myArray = ... илиmyArray = [NSArray arrayWithArray:...]; Вот он и дестройнулся и таблице неоткуда было брать данные.
Я предлагаю сначала сформировать массив из массивов вида:
MyArray:
абстрактно
item1
item1
item2
...
item2
item1
item2
...
И в методе cellForRowAtIndexPath делать следующее:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [[myArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
return cell;
}
Массив ячеек я имел в виду массив уже сформированых ячеек. Чтобы не формировать их в cellForRowAtIndexPath
Позже напишу если понадобится
#5
Отправлено 25 Июль 2012 - 20:57
Nikitich (25 Июль 2012 - 20:39) писал:
Значит вы его не проиниализировали myArray = [[NSArray alloc] initWithArray:..]; а просто присвоили myArray = ... или myArray = [NSArray arrayWithArray:...]; Вот он и дестройнулся и таблице неоткуда было брать данные.
Вы чертовски правы, я забыл проинициализировать
Теперь все работает, работает плавненько. Спасибо!
Nikitich (25 Июль 2012 - 20:39) писал:
Массив ячеек я имел в виду массив уже сформированых ячеек. Чтобы не формировать их в cellForRowAtIndexPath
Позже напишу если понадобится
Позже напишу если понадобится
Очень бы хотелось увидеть альтернативное решение
#6
Отправлено 10 Сентябрь 2012 - 06:46
Мне бы тоже хотелось увидеть... дело в том, что у меня таблица с фиксированным числом строк, но строки кастомные, т.е. каждая строка - это некий набор вьюшек - лейблов и кнопок. При прокрутке всё это дело лагает ужасно. Хочу нереальной оптимизации =)
#7
Отправлено 10 Сентябрь 2012 - 10:32
а какой у Вас xCode? Запустите диагностику и посмотрите, скорее всего утечки памяти. Начиная с 4.3 до 4.4 все ревью текут, сами по себе..
Куда пропали кнопки с телефонов?!
#8
Отправлено 10 Сентябрь 2012 - 12:01
Да нет. Утечки тут скорее всего не причем. Просто ячейки долго формируются.
Альтернативный вариант. Ячейки сначала формируются и кладуться в массив. А потом из уже сформированых ячеек строится таблица.
Но следует учитывать что в этом случае все ячейки будут лежать в памяти, это не совсем правильно, поэтому не стоит строить таблицу из 1000 ячеек таким способом.
Обычно есть массив с данными по ячейкам по которму строится каждая отдельная ячейка в cellForRowAtIndexPath. Пусть будет cellsDataArray. И в нем будут содержаться строки.
Но строить ячейки будем не в cellForRowAtIndexPath, а в viewDidLoad
Итак в .h файле объявили массив ячеек
Далее в .m файле во вьюдидлоад формируем массив ячеек.
Массив сформирован и теперь в cellForRowAtIndexPath нам останется вернуть только элемент этого массива согласноindexPath.
В общем как-то так. Я не сильно силен в объяснениях, если что будет не понятно, слеплю проект примера как будет время
Альтернативный вариант. Ячейки сначала формируются и кладуться в массив. А потом из уже сформированых ячеек строится таблица.
Но следует учитывать что в этом случае все ячейки будут лежать в памяти, это не совсем правильно, поэтому не стоит строить таблицу из 1000 ячеек таким способом.
Обычно есть массив с данными по ячейкам по которму строится каждая отдельная ячейка в cellForRowAtIndexPath. Пусть будет cellsDataArray. И в нем будут содержаться строки.
Но строить ячейки будем не в cellForRowAtIndexPath, а в viewDidLoad
Итак в .h файле объявили массив ячеек
NSArray *cellsArray;
Далее в .m файле во вьюдидлоад формируем массив ячеек.
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *cells = [NSMutableArray arrayWithCapacity:[cellsDataArray count]]; //Временный мьютабл массив
for (int i=0;i<[cellsDataArray count];i++)
{
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; //reuseIdentifier нам не нужен поскольку мы не будем юзать dequeueReusableCellWithIdentifier
cell.textLabel.text = [cellsDataArray objectAtIndex:i];
[cells addObject:cell];
}
cellsArray = [[NSArray alloc] initWithArray:cells]; //Инициализируем наш массив ячеек
}
Массив сформирован и теперь в cellForRowAtIndexPath нам останется вернуть только элемент этого массива согласноindexPath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [cellsArray objectAtIndex:indexPath.row];
}
В общем как-то так. Я не сильно силен в объяснениях, если что будет не понятно, слеплю проект примера как будет время
#10
Отправлено 27 Сентябрь 2012 - 22:32
А что будет, если в таблице должно быть 100500 записей? Это создаются 100500 ячеек и ложатся в массив? И что будет с памятью. Не гоните.
Таблица ж специально сделана так, что ячейки реюзались. Они создаются только для видимой области и реюзаются.
Посмотрите видео Understanding iOS View Compositing
Таблица ж специально сделана так, что ячейки реюзались. Они создаются только для видимой области и реюзаются.
Посмотрите видео Understanding iOS View Compositing
#11
Отправлено 28 Сентябрь 2012 - 10:20
Эм... я ж писал что это вариант для малого количества ячеек и не стоит так делать для 100500 ячеек. Читайте хоть.
Для 100500 ячеек конечно надо реюзабл использовать, никто не спорит. Но тогда если картинки брать с флешки таблица заметно притормаживает. Нужно придумывать какой-то механизм предварительной их загрузки/выгрузки из памяти частями.
Для 100500 ячеек конечно надо реюзабл использовать, никто не спорит. Но тогда если картинки брать с флешки таблица заметно притормаживает. Нужно придумывать какой-то механизм предварительной их загрузки/выгрузки из памяти частями.
No comments:
Post a Comment