Adaptive segue в раскадровке Xcode 6. Неужели устал?

Конструктор интерфейса Xcode 6 по умолчанию имеет новый флажок "Использовать классы размера". Это делает взгляды адаптивными. enter image description here

Когда я пытаюсь сделать segue между двумя видами в моей раскадровке, у меня есть новые опции: enter image description here

вместо старого:

enter image description here

Теперь у нас есть "show" и "present modally" вместо "push" и "modal". Старые параметры отмечены как устаревшие. Я выбрал вариант "показать" , потому что в настройках segue он назывался "show (например, push)

enter image description here

Но это не делает толчок. Анимация Segue выглядит как слайд снизу (модальный), а панель навигации исчезает.

Вопрос: как я могу заставить "показать" работу, как push? Возможно ли это или я должен использовать вместо этого "push (устаревший)"? Где я могу найти информацию о новых типах segue? Единственное, что я нашел в библиотеке разработчиков iOS8, - это Storyboards Help You Design Your User Interface, но нет информации о "show" segue.

UPDATE

Я попытался создать новый проект, и "показать" действительно работает как "push". Я думаю, что проблема в моем проекте может быть связана с тем, что я повторно использую навигационный контроллер с таким кодом, но я не знаю, как его исправить.

if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) {
    SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;

    swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {

        UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
        [navController setViewControllers: @[dvc] animated: NO ];
        [self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
    };

}

После этого я пытаюсь нажать NewViewController после MainViewController enter image description here

ОБНОВЛЕНИЕ 2:

Кажется, я только проблема iOS 7, iOS 7.1.

Ответ 1

Да, используйте 'Show вместо' Push

Как я могу заставить "показать" работу, как push? Возможно ли, или я должен использовать вместо этого "push (лишен)"?

Он должен; это для меня. Я использую Xcode 6 beta 2, и для тестирования я использовал единственный шаблон представления (вызывая предварительно созданный контроллер представления в IB 'VC_A). Затем я добавил еще один контроллер вида ('VC_B). Затем я добавил кнопку на VC_A, чтобы показать VC_B, а другой - от VC_B до VC_A. Когда я добавляю контроллер навигации в качестве начального контроллера представления в раскадровку и делаю VC_A rootViewController, то и "push", и "show" имеют тот же эффект. Если у меня нет начального контроллера навигации, и я использую 'show, я понимаю, что вы описали в том, что VC_B делает слайд снизу. Если я попытаюсь нажать, я получаю сбой, так как для того, чтобы сделать push, у меня должен быть контроллер навигации. Таким образом, кажется, что "шоу будет делать толкание в том случае, когда предусмотрен контроллер навигации, и делать подарок с модальным стилем перехода, если навигационного контроллера нет.

Где я могу найти информацию о новых типах segue?

Итак, я нашел некоторую информацию в разделе "Whats New in Interface Builder" здесь. Если вы посмотрите на слайды, вы увидите, что один слайд (41) упоминает об изменении. При просмотре этого сеансового видео вы можете пропустить минутку 38:00, где они начинают говорить об адаптивных выделениях. Они объясняют, что "show adaptive segue", например, учитывает контекст при принятии решения о том, как сделать презентацию нового контроллера представления.

Ответ 2

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

Как уже упоминалось ранее, "push" и "modal" segues были устаревшими и были заменены соответственно "show" и "present modally". Согласно документации Apple, новые сегменты были далее разделены на сегменты, которые адаптируются к классам размеров. Старшие должны использоваться только для поддержки версий iOS старше iOS 8.

Документ в следующей ссылке объясняет это и описание всех доступных сегов, старых и новых.

Добавление Segue между сценами в раскадровке

В случае изменения URL-адреса в будущем это объяснение для каждого нового сеанса:

Показать

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

Показать детали

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

Настоящий модем

Предоставить контент по тексту. Существуют варианты выбора стиля презентации (UIModalPresentationStyle) и стиля перехода (UIModalTransitionStyle).

Присутствовать как Popover

Представить контент как положу, привязанному к существующему виду. Существует возможность указать возможные направления стрелки, показанной на одном краю обзора (UIPopoverArrowDirection). Существует также возможность указывать якорный вид.

Ответ 3

TL;DR; Удалите Segue, который не толкает правильно и не воссоздает его в раскадровке, перетаскивая его из UIView/UIControl в цель просмотра.

Нет ничего плохого в других ответах, но в этом объясняется, что происходит, как вы можете проверить, что это происходит, и как смягчить проблему в будущем.

Фон

В моем случае ни один из моих Show Segues не работал, хотя у меня уже был UINavigationController в качестве моего начального контроллера представления (с моим содержимым UIViewController как его root).

Почему и как разрываются шоу Segue

Show segue ломается, когда у него есть действие, связанное с segue в источнике xml раскадровки. Типичный сценарий, вызывающий это, может быть, если вы переопределили segue из ранее введенного кода вручную. Это оставляет следующие биты в раскадровке xml.

<connections>
    <segue destination="85t-Z1-hxf" kind="show" identifier="ToOptions" action="showDetailViewController:sender:" id="gdZ-IX-KcN">
</connections>

Nota BeneПросмотр раскадровки как xml; Щелкните правой кнопкой мыши файл раскадровки и выберите Открыть как > Исходный код. Для возврата используйте Open as > Interface Builder - Storyboard

Чтобы выполнить любые пользовательские действия при использовании segue из раскадровки, вы можете просто нажать на prepareForSegue и перехватить контроллер представления назначения и вызвать любые методы из этого местоположения. В любом случае, побочный эффект для этой маленькой ошибки (ошибка заключается в том, что когда вы переопределяете segue, она неправильно настроена в xml ~ т.е. действие остается даже после вашего изменения segue на тот, который работает с UIView (или UIControl) в контроллер целевого представления).

К сожалению, наиболее прямое решение не выполняется. Поэтому просто удаление атрибута xml для действия из раскадровки будет НЕ устранить проблему. Вместо этого нужно просто удалить и воссоздать segue в раскадровке.

При воссоздании раскадровки xml больше не будет иметь действия, связанные с конкретным сегментом, и шоу будет выполняться как Push.

Пример Xml для правильного показа Segue

  <connections>
    <segue destination="RbV-Au-WV9" kind="show" identifier="ToOptions" id="5dm-os-bcS"/>
  </connections>

Смягчение

Чтобы предотвратить повторение, нужно просто придерживаться не-ручных раскадров, если это возможно, используя команду prepareForSegue для добавления необходимых действий на основе контроллера представления. Или, если вам нужно смешать и сопоставить, примите меры предосторожности, чтобы убедиться, что ваши шоу-сеги не имеют никаких действий, связанных с xml-раскадрой. Если вы имеете дело со старыми проектами, тогда вам следует уделить особое внимание исходному коду раскадровки, поскольку я обнаружил несколько проблем.

Ответ 4

Как Скотт Робертсон прокомментировал здесь, это выглядит как ошибка в iOS 7.

Похоже, что в iOS 8 переход выведен во время выполнения (правильное поведение), тогда как в iOS 7 переход выведен во время разработки (поведение с ошибкой).

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

Примечание: имитировать навигационную панель недостаточно для этих целей; вы должны иметь контроллер навигации в своем стеке push.

Чтобы воспроизвести ошибку:

  • Создайте новую раскадровку, в которой используются классы размеров.
  • Создайте два контроллера представления (нет контроллеров навигации).
  • Сделайте первый контроллер представления вторым контроллером просмотра с помощью Показать (например, Push) segue, связанный с кнопкой, например.
  • В коде отобразите первый контроллер представления, но вставьте его в контроллер навигации с помощью метода initWithRootViewController:.
  • Запустите приложение на iOS 7.
  • Нажмите кнопку, которая должна выполнить нажатие.
  • Вы получите модальный переход вместо нажатия на iOS 7. На iOS 8 вы получите правильное поведение нажатия.

enter image description here

Чтобы исправить ошибку:

  • Добавить контроллер навигации в раскадровку и установить первый контроллер представлений в качестве контроллера корневого представления. (Примечание: добавление второго, поскольку контроллер корневого представления НЕ исправит эту ошибку.)
  • Дайте ему идентификатор нежелательной почты, чтобы подавить предупреждение о недоступности навигационного контроллера и записать себе, что он существует только в качестве обходного пути. (например, workaround for show segues in iOS 7).

enter image description here

Обратите внимание, как контроллер навигации был добавлен во втором изображении и как он не имеет никаких входящих стрелок (т.е. не существует возможности его создания, кроме использования его идентификатора контроллера просмотра).

Ответ 5

Я знаю, что я опаздываю на это, но я хотел поделиться тем, что узнал. Это на самом деле ошибка и все еще присутствует сегодня (2014-12-18).

Я написал статью об этом здесь.

Это легко воспроизводится; на iOS8 будет работать только отлично и даже в iOS7.x, если вы не будете программно вставлять контроллер представления в стек перед вызовом Show segue.

Если вы только нажимаете на стек с помощью раскадровки, он будет работать; но, видимо, если вы нажмете через код каким-то образом, свойство navigationController нажатого UIViewController будет nil, а когда вы вызовете Show, он примет его модальный, потому что нет никакой навигации для управления стеком.

Только обходной путь до сих пор либо не нажимается на код (не выполнимо), либо использует устаревший Push.

Я подал радар (ссылка на статью). Не стесняйтесь записывать дубликаты с надеждой Apple на устранение этой проблемы.

Ответ 6

У меня была такая же проблема с segues в Xcode 7 и iOS 7.1.2. Show segues (новая функция от iOS 8) работает как modal segues в iOS 7 и не позволяет вам нажимать контроллеры View в стек контроллера навигации, когда вы определяете тип segue с Xcode в своей раскадровке. Вот почему ваш self.navigationController вернет нуль, потому что контроллер просмотра не был перенесен в стек, и вы не можете его поместить.

Я не понимаю, почему Apple не добавляла никаких уведомлений для этого случая в Xcode, когда вам нужно приложение для работы с iOS 7. Они говорят, что метод Push является устаревшим, но Show не работает корректно с iOS 7.

Что я сделал для решения проблемы:

Я создал класс MYShowSegue с .h

#import <UIKit/UIKit.h>

@interface MYShowSegue : UIStoryboardSegue

@end

И файл .m только с одним выполнить:

#import "MYShowSegue.h"

@implementation MYShowSegue

- (void) perform {

    if ([[[self sourceViewController] navigationController] respondsToSelector:@selector(showViewController:sender:)]) {

        id sender = nil;
        [[[self sourceViewController] navigationController] showViewController:[self destinationViewController] sender:sender];
    }else{

        [[[self sourceViewController] navigationController] pushViewController:[self destinationViewController] animated:YES];
    }
}

@end

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

Пользовательский пример Segue

Это решение поможет вам получить полную поддержку ваших приложений iOS 7, они будут использовать метод pushViewController для продвижения ваших просмотров и для iOS 8,9 и т.д. ваш segue будет работать с новыми ( iOS 8) метод showViewController

Не забудьте сделать то же самое со всеми вашими выделениями в своей раскадровке.

Ответ 7

Это все еще происходит в iOS 10.x

Удаление и повторное введение segues ничего не помогло мне:

Проблема: функция Required была 7 segues, которые работают только как "push" (на самом деле шоу Detail), но на самом деле только первый добавленный мной шаг будет толкать, остальные будут вести себя по-разному. Это несмотря на то, что Interface Builder описывает каждый из сегментов одинаково.

Решение: мне пришлось добавить действие к 6 сегментам, которые его не имели.

Оригинальная раскладушка XML

<connections>
  <segue destination="tIr-4a-WfZ" kind="showDetail" identifier="A" action="showViewController:sender:" id="8yd-Ne-7KA"/>
  <segue destination="4mB-YE-5dM" kind="showDetail" identifier="B" id="Uod-JC-786"/>
  <segue destination="Qh5-bJ-KcE" kind="showDetail" identifier="C" id="3PW-nV-hWl"/>
  <segue destination="EI6-f4-QBB" kind="showDetail" identifier="D" id="WUK-ju-KDm"/>
  <segue destination="nTz-N4-fpW" kind="showDetail" identifier="E" id="Id6-bW-Huc"/>
  <segue destination="JEp-CH-6dW" kind="showDetail" identifier="F" id="G0L-XW-7f4"/>
  <segue destination="AET-S1-O6h" kind="showDetail" identifier="G" id="3NK-93-wTy"/>
</connections>

Я изменил это, добавив showViewController: отправитель

<connections>
  <segue destination="tIr-4a-WfZ" kind="showDetail" identifier="A" action="showViewController:sender:" id="8yd-Ne-7KA"/>
  <segue destination="4mB-YE-5dM" kind="showDetail" identifier="B" action="showViewController:sender:" id="Uod-JC-786"/>
  <segue destination="Qh5-bJ-KcE" kind="showDetail" identifier="C" action="showViewController:sender:" id="3PW-nV-hWl"/>
  <segue destination="EI6-f4-QBB" kind="showDetail" identifier="D" action="showViewController:sender:" id="WUK-ju-KDm"/>
  <segue destination="nTz-N4-fpW" kind="showDetail" identifier="E" action="showViewController:sender:" id="Id6-bW-Huc"/>
  <segue destination="JEp-CH-6dW" kind="showDetail" identifier="F" action="showViewController:sender:" id="G0L-XW-7f4"/>
  <segue destination="AET-S1-O6h" kind="showDetail" identifier="G" action="showViewController:sender:" id="3NK-93-wTy"/>
</connections>