Странный сбой при использовании нового эффекта PageCurl при чтении PDF с MonoTouch и iOS 5.0 - PullRequest
3 голосов
/ 21 октября 2011

При использовании нового эффекта PageCurl при чтении PDF-файла с MonoTouch и iOS 5.0 я получаю странный сбой.Я сделал простой тестовый проект для MonoDevelop 2.8 и загрузил его на GitHub:

https://github.com/Emasoft/IpaziaPDFReader

Кажется, что что-то слишком рано получает GCd и убивает приложение, но я могуне найти что.Я пытался распорядиться всем разными способами, но тщетно.Я уже представил проект tarball команде Xamarin, но они не смогли решить эту проблему.

Что-то не работает в управлении памятью iOS NavigationController?Или я что-то упустил?

Любая помощь приветствуется, спасибо!

ОБНОВЛЕНИЕ: Я пытался удалить все подпредставления и подслои перед удалением объектов во всех классах, но он все еще не работает.Единственный способ избежать сбоя, который я обнаружил, - НИКОГДА не избавляться от страниц PDF, добавляя их в Список перед их выпуском, но это не является жизнеспособным решением, потому что таким образом память быстро расходуется для PDF со многими страницами иприложение все равно падает, когда не удается выделить память для следующей страницы.Еще один способ избежать сбоев - избавиться от страниц PDF ДО переворачивания страниц, форсируя метод dispose на контроллере страниц перед созданием нового контроллера страниц, но таким образом текущая страница станет пустой, а переход закручивает бесполезную пустоту.стр.Кажется, ни одно решение не работает.

Я обновил проект на GitHub тремя различными решениями, которые я пробовал (посмотрите в классе PageDataSource), вы можете раскомментировать их по одному, чтобы увидеть проблемы.

        //SOLUTION 1   
    void ForcingPageControllerDispose (BookPageController oldPageController)
    {
        // --- IF YOU UNCOMMENT THIS, THE CRASHES GO AWAY, BUT THE PAGE IN THE TRANSITION IS BLANK, SO IS NOT VIABLE
        currentPageController.View.RemoveFromSuperview ();
        currentPageController.Dispose ();
    }


    //SOLUTION 2
    void DisposeThePageControllerWhenDidFinishAnimating (BookPageController oldPageController, UIPageViewController pageViewController)
    {
        // --- IF YOU UNCOMMENT THIS, THE CRASHES STILL HAPPEN
        pageViewController.DidFinishAnimating += delegate(object sender, UIPageViewFinishedAnimationEventArgs e) {
            if (currentPageController != null) {
                currentPageController.View.RemoveFromSuperview ();
                currentPageController.Dispose ();
                Console.WriteLine ("currentPageController disposed for page: " + currentPageController.PageIndex);
            }
        };
    }


    //SOLUTION 3
    void BackupUnusedPagesToAvoidBeingGCd (BookPageController oldPageController)
    {
        // --- IF YOU UNCOMMENT THIS, THE CRASHES GO AWAY, BUT THE PAGES ARE NOT GARBAGE COLLECTED AND AFTER MANY PAGES IPHONE IS OUT OF MEMORY AND IT CRASHES THE APP
        if (parentController.book_page_controllers_reference_list.Contains (currentPageController) == false)
            parentController.book_page_controllers_reference_list.Add (currentPageController);
    }

Ответы [ 2 ]

1 голос
/ 22 октября 2011

Поскольку вы получаете зависимость от новых функций iOS 5, вам также следует принять новые API-интерфейсы View Controller в iOS 5, которые решают несколько проблем с контроллерами представления.

Я предлагаю вам проверить видео и слайды WWDC для сеанса 102 «Внедрение UIViewController Containment».

1 голос
/ 21 октября 2011

Я уже отправил архив проекта в команду Xamarin, но они не смогли решить проблему.

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

При быстром просмотре в вашем AppDelegate.cs неверно:

PageTurnViewController viewController = new PageTurnViewController ("PageTurnViewController", null);
window.AddSubview (viewController.View);

, начиная с локального viewController экземпляране будет никакой ссылки на него после того, как FinishedLaunching вернется, и GC сможет его забрать.Однако это необходимо (на нативной стороне) для того, чтобы View был полностью действителен.Это может привести к сбоям (могут быть и другие случаи, это первый и единственный файл, который я проверил сегодня утром).

Решение состоит в том, чтобы повысить viewController до поля.Это сделает его alive даже когда метод вернется, что сделает его недоступным для сбора.

ОБНОВЛЕНИЕ

Я быстро взглянул на ваш код на github.

  • Вы добавляете (под) вид, но никогда не удаляете их (когда GC удалит их, он не удалит их из супер-вида);

  • Вы теряете ссылки на представления, например, в PageDataSource.cs

            newPageController = new BookPageController (nextPageIndex, parentController.currentPDFdocument, parentController);
            return newPageController;
    

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

Для отладки вы можете добавить свои собственные финализаторы, например,

    ~BookPageController ()
    {
        Console.WriteLine ("bu-bye");
    }

и установить в них контрольные точки.Если они получают удар, а вы думаете, что он все еще используется, значит, вы, вероятно, обнаружили проблему.

...