Распределение объектов внутри цикла - PullRequest
1 голос
/ 09 июля 2011

Правильно ли размещать в цикле, чтобы создать несколько объектов?

for (int i = 0; i < limit; i++)  
{  
 UILabel *lbl = [[UILabel alloc] initWithFrame:(CGRectMake(i*20, 0, 20, 20))];  
 lbl.textColor = [UIColor whiteColor];  
 lbl.font = [UIFont systemFontOfSize:16];  
 lbl.backgroundColor = [UIColor blackColor];  
 lbl.text = [NSString stringWithFormat: @"%d", i];  
 [self.view addSubview:lbl];
 [lbl release];  
}  

В моем проекте я создаю сотни маленьких меток на нескольких uiscrollview панелях.И даже несмотря на то, что я вызываю метод release на этих ярлыках, у меня плохая производительность при жестах: даже после растеризации представлений.Чувствуется, что все эти ярлыки все еще там, ожидая, чтобы их сбросили из памяти.
Так что мой намек на проблему будет связан с тем, как я распределяю.

Чего мне не хватает? ...

Ответы [ 4 ]

3 голосов
/ 09 июля 2011

Память не будет освобождена, потому что вы добавляете UILabel s к представлению.Даже если вы вызываете release, потому что представление сохраняет их.

2 голосов
/ 09 июля 2011

Пока не выпущен self.view, все эти ярлыки продолжают существовать. Ваш код выделяет память и инициализирует объект, а затем передает право собственности на объект вашему представлению. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Когда вы не используете права доступа к ним, ваша release означает, что у вас не будет права владения ими, поэтому система будет свободна от них избавиться: ваша release сама не избавится от объектов. (Я добавил иллюстрацию ниже на случай, если она не ясна.)

Это не просто проблема с памятью, потому что объект UILabel имеет всевозможные дополнительные издержки: свои дюжину свойств и методов, несколько дюжин свойств и методов, которые он наследует от UIView, еще дюжину, унаследованных от UIResponder, и более еще десяток от UIObject. В результате UILabel может делать все изящные вещи: иметь цвета, тени и альфа-прозрачность, управлять переносом слов, подключать распознаватели жестов, быть анимированным и иметь собственные подпредставления и т. Д.

Для более легкого решения вы можете нарисовать тот же текст, используя метод drawInRect:withFont: NSString (который он получает из своих UIKit Additions ). Ничего из того, что UILabel накладных расходов, хотя ни один из его тонкостей, либо. Тем не менее, с небольшим усилием он должен делать именно то, что вы хотите.


Это, вероятно, излишнее, но иллюстрация:

Object Ownership Illustration

  1. Ваш ViewController выделяет и инициализирует View . В памяти есть одна копия View, и ViewController сохраняет право собственности на View до тех пор, пока вы (скорее всего) не отпустите ViewController в его методе dealloc (если только вы не выпустите его вручную ранее).

  2. Ваш ViewController выделяет и инициализирует Метка . В памяти имеется одна копия метки, и ViewController сохраняет за собой право собственности на метку.

  3. Вызывая метод addView представления, вы добавляете владение метки к представлению (в дополнение к указанию на отображение метки). В памяти по-прежнему есть одна копия метки, которой владеют два объекта.

  4. Вызывая метод Label release, ViewController отказывается от владения Label. В памяти по-прежнему есть одна копия метки, и View по-прежнему принадлежит ей.

Вы повторяете шаги 2 - 4 каждый раз в цикле, при этом View каждый раз сохраняет владение выделенной меткой.

Каждый раз, когда приложение достигает конца своего цикла выполнения (что происходит снова и снова во время работы приложения), если есть какие-либо выделенные объекты , у которых нет владельца , тогда память, используемая для их хранения, освобождается. Поскольку вашему представлению по-прежнему принадлежат все эти метки, память, выделенная для них, продолжает использоваться.

1 голос
/ 10 июля 2011

Сколько в вашем интерфейсе видимых пользователю ярлыков на экране в любой момент времени? Поскольку вы помещаете метки в UIScrollViews, я предполагаю, что пользователь видит значительно меньше, чем сотни, которые вы выделяете и рисуете одновременно. Если пользователь не видит сразу сотни ярлыков, зачем создавать их одновременно?

Вам следует подумать о принятии шаблона, аналогичного протоколу UITableViewDataSource. UITableView не выделяет 500 UITableViewCells заранее. Он запрашивает свой источник данных для ячейки только тогда, когда он должен быть нарисован. Кроме того, он будет перерабатывать ячейки, которые выходят за пределы экрана, чтобы компенсировать стоимость размещения / инициализации UITableViewCell с нуля. При правильной настройке в памяти будет только столько UITableViewCells, сколько пользователь сможет увидеть на экране.

Итак, подумайте о том, чтобы спроектировать UIScrollView так, чтобы он запрашивал метки только по мере их отрисовки, а затем сохранял неиспользуемые метки в памяти, когда они перемещались за пределы экрана. Таким образом, у вас в памяти будет только столько меток, сколько пользователь сможет увидеть на экране.

Есть некоторый пример кода, который показывает, как это сделать, используя UIScrollView подклассов:

ScrollViewSuite

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

0 голосов
/ 10 июля 2011

, если вы создаете сотни, это будет очень дорого и приведет к низкой производительности.

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

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

надеюсь, это поможет ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...