2014-01-02 8 views
2

Ok StackOverflow People ... У меня очень интересная проблема, которую я пытался решить в течение нескольких дней и не могу понять, поэтому мне нужно какая-то главная помощь. Это, скорее всего, будет очень длинным описанием, но, пожалуйста, несите меня и благодарите заблаговременно за то, что прочитали все это, потому что чем больше слов у меня есть, тем яснее я могу описать полную картину для всех вас. Я сделаю все возможное, чтобы быть как можно более кратким и последовательным. Пожалуйста, дайте мне знать, где бы я ни упал.UIRefreshControl Внутри UITableView, вызывающего приложение для замораживания при повороте - iOS 6+


Вот контекст моей проблемы: Я использую раскадровки для моего приложения IOS и для конкретной вкладки навигационной в моем приложении, мне пришлось создать две отдельные сцены и для портретного и альбомной ориентации. Причина для этого (вместо использования Autolayout) заключается в том, что на этой вкладке есть визуальные элементы (виды таблицы, веб-представления и т. Д.), Которые выложены по-разному в зависимости от ориентации, и это было намного проще создать отдельную сцену ориентации, чтобы справиться с этим изменением в пользовательском интерфейсе, а не делать это программно - (это также намного проще понять и более чисто по коду). Таким образом, убрать, чтобы иметь в виду все это, состоит в том, что эти две отдельные портретные и пейзажные сцены представляют собой ту же табуляцию в моем приложении. (Боковое примечание: эти сцены были сделаны в IB, конечно)

Теперь визуальные элементы, о которых я упоминал в пользовательском интерфейсе раньше - все глубже, все они контейнеры для разных UIViewControllers. Я изолировал все в приложении и в значительной степени имел отношение 1 к 1 для всех вещей, поэтому эти контейнеры будут сопоставляться с моим подклассом UIViewControllers, который я создал для их конкретных целей, - но это здесь, что первая оговорка моей проблемы возникает. Вот практический пример для более четкого изображения, у меня есть один UIViewController, который содержит UITableView под названием MXSAnnouncementsViewController, и этот же контроллер представлений существует как в пейзажной, так и в портретной сценах. Я не создавал явную портретную или ландшафтную версию этого контроллера представления, но вместо этого попросите контроллер отслеживать два свойства IBOutlet (tableViewLandscape и tableViewPortrait), которые указывают на ориентированный на ориентацию UITableViews - и этот подход работает отлично. Более того, в моем MXSAnnouncementsViewController у меня есть локальное свойство, называемое tableView, которое абстрагирует ориентированные на ориентацию таблицы. Он получает набор в viewDidLoad, которые вы можете увидеть ниже:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    if (self.tableViewPortrait) { 
     self.tableView = self.tableViewPortrait; 
    } else { 
     self.tableView = self.tableViewLandscape; 
    } 

    [self.tableView setDelegate:self]; 
    [self.tableView setDataSource:self]; 

    if (![MXSAnnouncementManager sharedAnnouncementManager].latestAnnouncements) { 
     [MXSAnnouncementManager loadModel:@"MXSAnnouncementGroupAllAnnouncements" withBlock:^(id model, NSError *error) { 
      if (!error) { 
       self.arrayLatestAnnouncements = [MXSAnnouncementManager sharedAnnouncementManager].latestAnnouncements; 
       [self.tableView reloadData]; 
      } else { 
       // show some error msg 
      } 
     }]; 
    } else { 
     self.arrayLatestAnnouncements = [MXSAnnouncementManager sharedAnnouncementManager].latestAnnouncements; 
    } 

    [self setupPullToRefresh]; 
} 

Всякий раз, когда я нахожусь на вкладке, одна из двух ориентации специфичной IBOutlets всегда активен и имеет адрес в памяти, а другой nil. Всякий раз, когда я вращаюсь, роли обратные - то, что ранее имело адрес в памяти, теперь nil, а другое было инициализировано и выделено, поэтому я делаю то, что я сделал с свойством tableView в приведенном выше фрагменте. Вот здесь в картине появляется caveat # 2, и это doozy - это связано с жизненным циклом представления. Вот практический пример для ясности: Скажем, я загружаю приложение в альбомную ориентацию. Когда я это сделаю, у моей розетки tableViewLandscape есть адрес в памяти, а мой вывод tableViewPortrait - nil. Это ожидаемое и желаемое поведение. Теперь, когда я поворачиваю приложение, начинается сумасшедший материал. Вот одно место, где мне нужна ясность от всех вас в отношении случаев UIViewControllers, и что нормально, и что не так читать ОЧЕНЬ медленно и осторожно.

Вращение приложения сразу вызывает противоположную сцену ориентации (другая ИНСТАНЦИЯ MXSAnnouncementsViewController ???), чтобы вызвать ее метод viewDidLoad (в этом примере мы находимся в Пейзаже, так что сценарий Portrait вызывает этот метод). В этом методе мое локальное свойство tableView получает текущее активное представление таблицы для этой ориентации (см. Фрагмент выше).Когда этот метод заканчивается, предыдущий экземпляр LANDSCAPE MXSAnnouncementsViewController вызывает его метод viewWillDisappear, за которым следует вызов экземпляра PORTRAIT его метода viewWillAppear, который затем заканчивается экземпляром LANDSCAPE, вызывающим его обратный вызов willRotateToInterfaceOrientation, - это порядок работы, который I ' видя из точек останова. Я действительно надеюсь, что у тебя все получилось, потому что мой разум просто взорвался от всего этого.

Если вы все еще со мной на данный момент, спасибо, потому что мы наконец-то на родине. Как видно из названия этого сообщения, проблема, которую я пытаюсь решить, - это мое приложение, зависящее от вращения. Если вы не заметили на viewDidLoad сниппета, последняя команда, чтобы получить казнены является setupPullToRefresh метод, который заключается в следующем:

- (void)setupPullToRefresh 
{ 
    UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; 
    [refreshControl addTarget:self action:@selector(refreshTableView:) forControlEvents:UIControlEventValueChanged]; 
    [self.tableView addSubview:refreshControl]; 
} 

Так как я уже объяснил весь вид жизненного цикла порядок операций по ротации ранее, чтобы сделать очень длинная история, если я прокомментирую последнюю инструкцию setupPullToRefresh в конце viewDidLoad за MXSAnnouncementsViewController, мое приложение отлично работает. Если я включу эту инструкцию, мое приложение перестанет отвечать на первое вращение, и я не могу понять, почему. Не уверен, что я имею дело с краевым случаем здесь или еще чем-то. Любые и всякие идеи приветствуются, и БЛАГОДАРИМ ВАС СКОЛЬКО для чтения всего этого!

+0

Что приложение делает, пока он висит, основной поток? –

+0

Я еще не профессионал в области разработки и отладки iOS, но я просто попытался использовать инструменты, и это не похоже на то, что основной поток ничего не делает. Я вижу что-то, что говорит <Достигнутый предел стека вызовов>, но я не уверен, что это значит. Я мог определенно копать глубже в небольшом направлении, но я так же полезен, как камень на земле один. – Danchez

+0

Иногда возникают подсказки, когда вы приостанавливаете приложение с помощью || и посмотрите на стек основного потока. Разумеется, разуплотнение - снова несколько раз может дать разные результаты стека. –

ответ

1

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

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

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

0
  • Попробуйте добавить его после того, как вращение

    -(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{ 
        [self setupPullToRefresh]; 
    } 
    
  • Если это не поможет, создавать UIRefreshControl только один раз и установить его в таблице справа при повороте.

  • Если это не помогает тоже, вслед за первым дал ответ (@ ответ Гэвина) и создать только один стол на viewDidLoad и relayout вещи в -(void)viewWillLayoutSubviews

Смежные вопросы