UIPageViewController падает, когда переворачивается слишком быстро во время нехватки памяти

У меня были некоторые проблемы с памятью из-за шаблона XCode для UIPageViewController, кэширующего все данные страницы, поэтому я изменил его, чтобы динамически загружать страницы, поэтому теперь, когда мое приложение получает предупреждение о нехватке памяти, оно освобождает память для страниц, которые не загружаются. показ, но если пользователь очень быстро перелистывает страницы, нажав на край экрана, он все равно падает. Я предполагаю, что это потому, что он не может освободить память достаточно быстро, когда вызывается didReceiveMemoryWarning. Если пользователь медленно переворачивает, он работает нормально. Я ограничил скорость, с которой пользователь может переворачивать страницы, но это все же происходит. Я хочу иметь возможность освобождать память каждый раз, когда страница переворачивается, и мне не нужно ждать предупреждения о нехватке памяти. Я использую ARC. Есть ли способ сделать это? Или что еще я могу сделать, чтобы предотвратить это? Благодарю.

РЕДАКТИРОВАТЬ:

<code>(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    NSUInteger index = [self indexOfViewController:(SinglePageViewControllerSuperclass *)viewController];
    if ((index == 0) || (index == NSNotFound)) {
        return nil;
    }

    index--;
    return [self viewControllerAtIndex:index];
} 

(UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    NSUInteger index = [self indexOfViewController:(SinglePageViewControllerSuperclass *)viewController];
    if (index == NSNotFound || index == MAX_PAGE_INDEX) {
        return nil;
    }

    return [self viewControllerAtIndex:++index];
}
</code>
 Rok Jarc02 июн. 2012 г., 13:17
Пожалуйста, отправьте код вашего- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController а также- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController методы.
 futureelite728 мая 2012 г., 03:39
Сначала разместите свой код, это будет очень полезно.

Ответы на вопрос(5)

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

Одно из решений - настроить слой и кэшировать результат рендеринга. Перерисовывать контент только тогда, когда необходимо. Но кеш может увеличить использование памяти.

 Add080bbA27 окт. 2014 г., 17:14
кажется, у меня такая проблема. Можете ли вы дать более подробную информацию? Что вы подразумеваете под рендерингом кеша? Я пытаюсь создать приложение для детей. Нечто похожее на звуки животных. В каждой детали животного присутствует ключевая анимация и звук. Контроллер представления каждой детали животного находится в контроллере uipageview. При перемещении вправо, когда я нажимаю на животное, запускается анимация ключевого кадра caLayer и воспроизводится звук. UiPageviewController уже увеличивает использование памяти, CALayer анимация анимации животных является последним ударом. Что я могу сделать

которое я сделал, и кто-то может счесть полезным:

В основном, я разрешаю начинать перелистывание новой страницы только в том случае, если предыдущая завершилась.

Я использую проект Apple PageViewController по умолчанию в качестве шаблона, поэтому я буду использовать термины, определенные в этом проекте.

Когда бы VC страницы не запрашивался через viewControllerAtIndex :, я устанавливаю логическое значение для ModelController с именем 'shouldDenyVC 'доYES.

В моем EbookViewController, который является делегатом UIPageViewController, я фиксирую распознаватели жестов и назначаю EbookViewController в качестве их делегата:

self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
for (UIGestureRecognizer *gr in self.view.gestureRecognizers) {
    gr.delegate = self;
}

Затем я могу отказать в повороте страницы, запретив распознаватели жестов:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:    (UITouch *)touch
{
    if (_modelController.shouldDenyPageTurn == YES) {
        return FALSE;
    }
    return TRUE;
}

И наконец, я поставил_modelController.shouldDenyPageTurn = NO в конце метода делегата UIPageViewControllerpageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:

Мне тоже нужно было установить_modelController.shouldDenyPageTurn = NO в конце любой предварительной загрузки, чтобы можно было переворачивать страниц

Решение Вопроса

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

У тебя есть три подхода к этому, ИМО:

реализовать "свет"viewDidLoad метод (фактически вся последовательность инициализации / начального отображения): в некоторых приложениях имеет смысл, например, загружать изображение с низким разрешением вместо изображения с высоким разрешением, которое будет отображаться; или, немного задерживая выделение дополнительных ресурсов, необходимых вашей странице (доступ к базе данных, звук и т. д.);

использовать пул страниц, скажем, массив из трех страниц (или 5, это зависит от вашего приложения), чтобы вы продолжали «повторное использование», чтобы профиль памяти вашего приложения оставался стабильным и избегал всплесков;

внимательный обзор того, как вы распределяете и освобождаете память; в этом смысле вы часто читаете, что авто-релиз добавляет некоторую «инерцию» к механизму освобождения / освобождения, и это довольно легко понять: если у вас есть объект автоматического освобождения, он будет освобожден пулом релиза только при циклическом переключении основной цикл (это верно для основного пула релизов); поэтому, если у вас есть длинная последовательность методов, которые вызываются при перелистывании страницы, это приведет к тому, что release / dealloc произойдет позже.

Когда дело доходит до оптимизации использования памяти, нет волшебной точки зрения, это довольно детальная и тяжелая работа, но в IME вы сможете уменьшить профиль памяти своего приложения, если вы просмотрите свой код и примете эти 3 правила. В частности, проверка всплесков выделения памяти в инструментах и попытка понять, с чем они связаны, чрезвычайно эффективны.

 Marty03 окт. 2012 г., 19:34
Дополнительная полезная информация. Инженер Apple сказал мне, что начиная с iOS6, «viewWillAppear» вызывается, когда страница становится видимой (когда начинается перелистывание страницы), и «viewDidAppear» вызывается, когда страница завершает поворот. Я еще не пробовал, просто подумал упомянуть. Используя это, вы можете заблокировать возможность переворачивать страницу, пока предыдущая не закончила (игнорируя жесты / прикосновения).

из-за которой представление прокрутки теряет небольшой объем памяти.

Вы пробовали профилировать свое приложение в инструментах, проверяя распределение и утечки памяти?

Вы можете имитировать предупреждение о нехватке памяти либо в симуляторе (аппаратная часть -> имитировать предупреждение о нехватке памяти). Или вы можете сделать это с помощью кода (просто не забудьте удалить после отладки, потому что это приведет к отклонению вашего приложения!)

[[UIApplication sharedApplication] performSelector:@selector(_performMemoryWarning)];

Если вы используетеstrong илиretain свойства затем установите их наnil когда вы закончите с ними, и ARC освободит память, на которую они указывают, за кадром.

Если вы создаете много временных объектов (объектов, которые не являются свойствами или не выделены), затем вставьте пул автоматического выпуска:

@autoreleasepool {

}

И, наконец, покажи код, и мы сможем помочь тебе.

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

Для принудительной выгрузки вида вы можете переопределитьviewDidDisappear: метод тех классов viewcontroller, которые появляются вUIPageViewController.

Код будет выглядеть так:

- (void)viewDidDisappear:(BOOL)animated {
    [self didReceiveMemoryWarning];
}

Если у вас есть переопределение didReceiveMemoryWarning, не забудьте позвонить[super didReceiveMemoryWarning]; от него

Там также может быть некоторая путаница о том, какUIPageViewControllerDataSource методы работают - у вас могут быть какие-то «смешанные провода». Проверить принятый ответВо.

Ваш ответ на вопрос