Створення каналу програмно


202

У мене є загальним, UIViewControllerщо всі мої UIViewsControllersрозширюються, щоб повторно використовувати деякі загальні операції.

Я хочу налаштувати на цьому "Спільному" UIViewControllerпотяг, щоб усі інші UIViewControllersуспадкували.

Я намагаюся зрозуміти, як це зробити програмно.

Я здогадуюсь, що питання також може полягати в тому, як мені встановити segueвсі свої, UIViewControllersне заходячи в дошку розповідей і робити їх вручну.

Відповіді:


169

За визначенням, сейг дійсно не може існувати незалежно від раскадровки. Це навіть там , в імені класу: UIStoryboardSegue. Ви не створюєте модні програми програмно - саме час виконання розкадровки створює їх для вас. Зазвичай ви можете зателефонувати performSegueWithIdentifier:у код контролера свого перегляду, але це покладається на те, що для посилання вже встановлено відомий канал у дошці.

Я думаю, що ви запитуєте, це те, як ви можете створити метод у вашому загальному контролері перегляду (базовий клас), який перейде до нового контролера перегляду та буде успадкований усіма похідними класами. Ви можете зробити це, створивши такий метод, як цей у вашому контролері подання базового класу:

- (IBAction)pushMyNewViewController
{
    MyNewViewController *myNewVC = [[MyNewViewController alloc] init];

    // do any setup you need for myNewVC

    [self presentModalViewController:myNewVC animated:YES];
}

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


4
Дякую. Прикро, що ми не можемо це зробити програмно. Це дійсно підвищить якість вихідного коду (менше дублювання завжди добре). Я поїду з вашою пропозицією.
Тіаго Велозу

2
@jonkroll чи можна викликати / виконати segue з оператора switch, тобто на основі того, який індекс у мене є?
codejunkie

5
@codejunkie: Так, ви можете це зробити. Для цього ви використовуєте UIViewControllerназваний метод performSegueWithIdentifier:sender:.
jonkroll

2
Я створював та виконував програмне забезпечення Segue (див. Мою відповідь). Щось з моїм кодом не так, якщо ваша відповідь правильна?
Жан-Філіп Пеллет

13
Оновлення для iOS 6+: UIViews presentModalViewController:animated:застаріле. З документів - (застаріло в iOS 6.0. Використовуйте presentViewController: анімований: завершення: замість цього)
користувач

346

Я думав, що додам ще одну можливість. Однією з речей є те, що ви можете з’єднати дві сцени на дошці розкадрування за допомогою каналу, який не прикріплений до дії, а потім програмно запустити виразку всередині вашого контролера перегляду. Як ви це зробите, це те, що вам потрібно перетягнути значок піктограми власника файлу в нижній частині сцени розкадрівки, яка є сценою заїдання, і перетягнути праворуч до місця призначення. Я накину зображення, щоб допомогти пояснити.

введіть тут опис зображення

З'явиться спливаюче вікно для "Ручного Segue". Я вибрав Push як тип. Торкніться маленької площі та переконайтеся, що ви є інспектором атрибутів. Дайте йому ідентифікатор, який ви будете використовувати для позначення його в коді.

введіть тут опис зображення

Гаразд, далі я збираюся провести пошук за допомогою елемента програмної кнопки на панелі. У viewDidLoad або десь іншому я створить на панелі навігації елемент кнопки з цим кодом:

UIBarButtonItem *buttonizeButton = [[UIBarButtonItem alloc] initWithTitle:@"Buttonize"
                                                                    style:UIBarButtonItemStyleDone
                                                                   target:self
                                                                   action:@selector(buttonizeButtonTap:)];
self.navigationItem.rightBarButtonItems = @[buttonizeButton];

Гаразд, зауважте, що селектор buttonizeButtonTap:. Тому напишіть метод пустоти для цієї кнопки, і в межах цього методу ви зателефонуєте до каналу так:

-(void)buttonizeButtonTap:(id)sender{
    [self performSegueWithIdentifier:@"Associate" sender:sender];
    }

Параметр відправника необхідний для ідентифікації кнопки під час виклику PrepaForSegue. PrepaForSegue - це метод фреймворку, де ви будете інстанціювати свою сцену та передавати їй будь-які значення, необхідні для її роботи. Ось як виглядає мій метод:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"Associate"])
    {
        TranslationQuizAssociateVC *translationQuizAssociateVC = [segue destinationViewController];
        translationQuizAssociateVC.nodeID = self.nodeID; //--pass nodeID from ViewNodeViewController
        translationQuizAssociateVC.contentID = self.contentID;
        translationQuizAssociateVC.index = self.index;
        translationQuizAssociateVC.content = self.content;
    }
}

Добре, просто перевірив це, і він працює. Сподіваюся, це допоможе вам.


@MichaelRowe, як це усуває потребу в сегах? Як я бачу, вам все одно доведеться перетягувати на
аркуші розгортки

@MichaelRowe це не позбавляє від потреби в сегах. З цього ви можете перейти між контролерами перегляду, які вбудовані в код, а не в інтерфейсі.
Метью

@Matt це насправді просто перегляньте, як я налаштовую свою програму ... Після повного переписування всього інтерфейсу я більше не використовую жодних мотивів ..
Майкл Роу,

@cocoanut Я отримую помилку, оскільки "Програма намагалася представити модально активний контролер" будь-яку допомогу щодо цього ..
Бала

1
Посібник Segue "Push" застарів, використовуйте "Показати". У цій відповіді є детальніше. @smileBot, будь ласка, оновіть відповідь.
NAbbas

81

Я використовую цей код, щоб створити власний підклас Segue і запустити його програмно. Здається, працює. Щось з цим не так? Я спантеличений, читаючи всі інші відповіді, в яких говорилося, що цього не можна зробити.

UIViewController *toViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"OtherViewControllerId"];
MyCustomSegue *segue = [[MyCustomSegue alloc] initWithIdentifier:@"" source:self destination:toViewController];
[self prepareForSegue:segue sender:sender];
[segue perform];

4
Що є в MyCustomSegue?
Віктор Енгель

3
Це спеціальний підклас UIStoryboardSegue.
Жан-Філіп Пеллет

7
@MarkAmery Багато людей (включаючи мене) уникають використання раскадров. Їх важко об'єднати, і не існує перевірки часу компіляції, чи ідентифікатор, через який я передаю performSegueWithIdentifier:, дійсно визначений у раскадровці. Я уникаю всіх проблем, якщо сам створюю сегу.
Жан-Філіп Пеллет

3
Я згоден з Жаном-Філіппом. Управління розкадровкою - це біль у задниках. Звичайно, легко натиснути свій шлях шляхом створення декількох поглядів і додавання сюди та туди, але керувати 6 переглядами з 16 сег, визначених у XML, коли у вас є три розробники, всі з якими стикаються, це жахливо. У будь-якому разі, справа в тому, що код дає вам контроль, xml, створений xcode, не робить.
Кристян

3
Я бачу збій у [segue perform] в iOS7, не впевнений, чи відчуває це хтось інший.
Ерік Чен

45

Здогадайтесь, на це відповіли і прийняли, але я просто хотів би додати ще кілька деталей до нього.

Що я зробив, щоб вирішити проблему, коли я представив би перегляд входу як перший екран, а потім хотів перейти до програми, якщо вхід був правильним. Я створив segue від контролера перегляду входу до контролера кореневого виду і дав йому ідентифікатор типу "myidentifier".

Потім після перевірки всього коду входу, чи вхід був правильним, я б зателефонував

[self performSegueWithIdentifier: @"myidentifier" sender: self];

Найбільше моє непорозуміння полягало в тому, що я намагався натиснути на канал і ніби перервав вираз, коли його було знайдено.


4
Як я вже писав як інший коментар: я створював і виконував власні програмні програми (див. Мою відповідь).
Жан-Філіп Пеллет

32

Ви повинні зв’язати свій код із тим, UIStoryboardщо використовуєте. Переконайтеся, що ви зайшли у YourViewController у своєму UIStoryboard, натисніть на межі навколо нього, а потім встановіть його identifierполе на значення, NSStringяке ви викликаєте у своєму коді.

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" 
                                                     bundle:nil];
YourViewController *yourViewController = 
 (YourViewController *)
  [storyboard instantiateViewControllerWithIdentifier:@"yourViewControllerID"];
[self.navigationController pushViewController:yourViewController animated:YES];

1
Я це розумію, але що робити, якщо viewController, який я хочу представити, вбудований у NavigationController у дошці розкадрувань? З того, що я можу знайти, я можу ініціалізувати NavigationController, щоб вбудувати його, але в аркуші розкадровки у мене вже є налаштування push-seges для подання, яке потрібно представити.
jhilgert00

1
Ви можете детальніше розглянути це? Я думаю, це проблема у мене є, але я не можу знайти, як / де це зробити ...
jesses.co.tt

1
Навіть це рішення є правильним, мова йде про те, щоб уникнути будь-якої смути, але питання стосується сеги. Таким чином ви можете підключити або здійснити перехід між двома сценами БЕЗ шва у розкладачах.
BootMaker

16

Для контролерів, які знаходяться в розкадровці.

jhilgert00 це те, що ви шукали?

-(IBAction)nav_goHome:(id)sender {
UIViewController *myController = [self.storyboard instantiateViewControllerWithIdentifier:@"HomeController"];
[self.navigationController pushViewController: myController animated:YES];

}

АБО ...

[self performSegueWithIdentifier:@"loginMainSegue" sender:self];

3

добре, ви можете створити, а також можете підкласировать UIStoryBoardSegue. субкласифікація в основному використовується для надання анімації користувальницького переходу.

ви можете побачити відео wwdc 2011, що представляє StoryBoard. також доступний у ютубі.

http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIStoryboardSegue_Class/Reference/Reference.html#//apple_ref/occ/cl/UIStoryboardSegue


3

Я хотів би додати уточнення ...

Поширене непорозуміння, насправді таке, яке я мав протягом певного часу, полягає в тому, що цей prepareForSegue:sender:метод спрацьовує на сцені розкадровки . Це не. Програма розкадрівки виконуватиметься незалежно від того, чи застосували ви prepareForSegue:sender:метод для цього (відходячого від) контролера перегляду.

Я дізнався про це з чудових лекцій Пола Гегарті iTunesU . Мої вибачення, але, на жаль, не можу пригадати, яку лекцію.

Якщо ви підключите вивід між двома контролерами подання на дошці розкадрівки, але не реалізуєте prepareForSegue:sender:метод, він все одно перейде на контролер цільового виду. Однак, цей контролер виглядає непідготовленим.

Сподіваюсь, це допомагає.


3

Сегери для розгортання не повинні створюватися поза розгорткою. Вам потрібно буде підключити його, незважаючи на недоліки.

UIStoryboardSegue Reference чітко зазначає:

Ви не створюєте безпосередньо об’єкти шва. Натомість, час виконання арсеналу створює їх тоді, коли він повинен виконувати вираз між двома контролерами перегляду. Ви все ще можете ініціювати програму програми за допомогою методу performSegueWithIdentifier: sender: UIViewController, якщо ви хочете. Ви можете зробити так, щоб ініціювати сказ із джерела, доданого програмно і тому недоступного в Інтерфейсі.

Ви все ще можете запрограмувати програму розкадрування, щоб представити контролер перегляду за допомогою Segue за допомогою presentModalViewController:або pushViewController:animated:викликів, але вам знадобиться екземпляр розкадрування.

Ви можете зателефонувати UIStoryboardз методом класу s, щоб отримати іменовану розкадровку з нульовим пакетом для основного пакету.

storyboardWithName:bundle:


2

По-перше, припустимо, у вас є два різних погляди на раскадровці, і ви хочете переходити з одного екрана на інший, тому виконайте наступні дії:

1). Визначте всі свої погляди за допомогою файлу класу, а також ідентифікатора розкадрівки в інспекторі особи.

2). Переконайтеся, що ви додали навігаційний контролер до першого виду. Виберіть його на аркуші розкадрування, а потім Редактор> Вставити> Контролер навігації

3). У першому класі імпортуйте "secondClass.h"

#import "ViewController.h
#import "secondController.h"

4). Додайте цю команду в IBAction, який повинен виконувати segue

secondController *next=[self.storyboard instantiateViewControllerWithIdentifier:@"second"];
[self.navigationController pushViewController:next animated:YES];

5). @"second"- клас контролера secondview, ідентифікатор.


self.storyboardповинно бути:UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
masipcat

@masipcat та назва ради Story можуть залежати від того, як ви створили проект Xcode, в моєму це було "Main.storyboard", тому я використовувавstoryboardWithName:@"Main"
ammianus

@ sanket-chauhan, якщо ваш перший контролер не вбудований у навігаційний контролер, ви також можете показати наступний вигляд, використовуючи [self showDetailViewController:next sender:self];або[self showViewController:next sender:self];
ammianus

1

Я здійснив реверс-інженерію та здійснив відкриту (повторну) реалізацію сфер UIStoryboard: https://github.com/acoomans/Segway

За допомогою цієї бібліотеки ви можете визначити seges програмно (без будь-якої розкадровки).

Сподіваюся, це може допомогти.


0

Насправді кілька проблем:

По-перше, у тому проекті, який ви завантажили для нас, segue не має ідентифікатора "segue1":

немає ідентифікатора

Ви повинні заповнити цей ідентифікатор, якщо ви ще цього не зробили.

По-друге, під час переходу від подання таблиці до подання таблиці ви викликаєте initWithNibName, щоб створити контролер перегляду. Ви дійсно хочете використовувати instantiateViewControllerWithIdentifier.


0

Ось зразок коду для Creating a segue programmatically:

class ViewController: UIViewController {
    ...
    // 1. Define the Segue
    private var commonSegue: UIStoryboardSegue!
    ...
    override func viewDidLoad() {
        ...
        // 2. Initialize the Segue
        self.commonSegue = UIStoryboardSegue(identifier: "CommonSegue", source: ..., destination: ...) {
            self.commonSegue.source.showDetailViewController(self.commonSegue.destination, sender: self)
        }
        ...
    }
    ...
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // 4. Prepare to perform the Segue
        if self.commonSegue == segue {
            ...
        }
        ...
    }
    ...
    func actionFunction() {
        // 3. Perform the Segue
        self.prepare(for: self.commonSegue, sender: self)
        self.commonSegue.perform()
    }
    ...
}

Ви телефонуєте self.prepare(for: self.commonSegue, sender: self)зі свого способу дії. Тоді який сенс порівнювати if self.commonSegue == segue {...}в prepare(for:sender)методі?
найем

@nayem: В prepare(for:sender:), ви можете налаштувати контролер подання призначення до його відображення. Звичайно, ви також можете це зробити actionFunction.
jqgsninimo

@nayem: Причиною цього я є намагатися бути узгодженим з поводженням з іншими сегами.
jqgsninimo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.