Способы передачи данных между контроллерами swift

Передача данных между контроллерами в Swift

О Свифт

Swift — это замечательный язык программирования, который Apple представила во время WWDC 2014, и теперь почти все разработчики Apple используют его для программирования приложений iOS и OS X. Он очень гибкий, более простой в использовании, чем его предшественник Objective C, и сэкономит вам драгоценные минуты при кодировании с помощью XCode.

Это мощный и интуитивно понятный язык программирования для iOS, OS X, tvOS и watchOS. Написание кода Swift интерактивно и увлекательно, синтаксис лаконичен, но выразителен, а Swift включает в себя современные функции, которые любят разработчики. Если вы еще не используете Swift, ознакомьтесь с некоторыми другими нашими великолепными учебниками по языку Swift:

Об этом уроке

В большинстве случаев, когда вы создаете приложение для iOS с несколькими экранами, вам нужно передавать данные между вашими контроллерами представления, чтобы они могли обмениваться контентом, не теряя их в процессе. В этом уроке вы узнаете, как это сделать. Мы будем использовать String , Integer , а также UIImage , так что продолжайте читать — вы будете удивлены, насколько легко эта работа с Swift.

Настройка проекта XCode

Прежде всего, создайте новый проект XCode. Выберите Single View Application и назовите проект так, как вам нравится. Вы найдете файл ViewController.swift в списке файлов на левой панели и интерфейс контроллера в раскадровке.

Начните с перетаскивания нового View Controller из библиотеки объектов на раскадровку.

Вставьте ваш первый контроллер в NavigationController , чтобы при переходе к следующему контроллеру в верхней панели отображалась кнопка « Назад» по умолчанию. Теперь выберите первый контроллер в раскадровке и нажмите « Редактор» > « Встроить в …» > « Контроллер навигации» .

Теперь добавьте UILabel и UIButton к контроллеру. Вы можете найти их в библиотеке объектов и перетащить в ваш первый контроллер. Затем дважды щелкните UILabel и введите текст, который вы хотите передать второму контроллеру. Я только что установил его текст « Текст для передачи ».

На втором контроллере перетащите новую UILabel куда хотите и просто оставьте текст таким, какой он есть.

Теперь нам нужно создать новый файл .swift и прикрепить его ко второму контроллеру. Итак, щелкните правой кнопкой мыши на панели списка файлов слева, выберите « Новый файл …» , выберите « Какао Touch Class» из категории « Источник iOS », нажмите « Далее» и назовите новый контроллер представления SecondVC . (В имени не должно быть пробелов, и оно должно начинаться с заглавной буквы.)

Теперь вам нужно связать второй контроллер в раскадровке с вашим новым файлом SecondVC.swift . Выберите желтый кружок в верхней части контроллера, щелкните значок панели « Определить инспектор» в правой части окна XCode и введите имя нового файла .swift в полях Class и StoryboardID .

Подключение видов к файлам .swift

Разбейте окно XCode на две части, нажав кнопку « Помощник редактора» в правом верхнем углу. Теперь у вас будет раскадровка слева, а соответствующий файл .swift — справа.

Соедините UILabel как IBOutlet и UIButton как IBAction с вашим файлом .swift , удерживая правую кнопку мыши (или клавишу Control и кнопку мыши) над этими представлениями и перетаскивая синюю линию прямо под объявлением class .

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

Как только вы закончите соединять все представления, разделите окно XCode на две части и выберите первый контроллер на раскадровке. Теперь с правой стороны отобразится файл ViewController.swift, и вы будете готовы написать в нем некоторый код.

Читайте также:  Коэн кун способ настройки

Давайте код!

Поместите следующий код в метод goButton() .

Источник

Как Вы делитесь данными между контроллерами представлений и другими объектами в Swift?

Скажем, у меня есть несколько контроллеров представления в моем приложении Swift, и я хочу иметь возможность передавать данные между ними. Если я нахожусь на несколько уровней ниже в стеке контроллера вида, как мне передать данные другому контроллеру вида? Или между вкладками в контроллере представления панели вкладок?

(Обратите внимание, что этот вопрос является «ringer».) Об этом спрашивают так много, что я решил написать учебник по этому предмету. См. мой ответ ниже.

8 ответов

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

Мне было интересно, как я могу поделиться объектами NSDictionary между несколькими контроллерами представления, которые в основном являются вкладками в моем приложении. Я попробовал использовать протокол, как в Java, чтобы я мог привести к протоколу и получить доступ к свойству. Это, кажется, не.

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

Наиболее распространенный сценарий, о котором спрашивают на Stack Overflow в моем опыте, — это простая передача информации от одного контроллера представления к другому.

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

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

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

Мы также можем захотеть поделиться информацией между вкладками в UITabBarController .

В этом случае это на самом деле потенциально еще проще.

Во-первых, давайте создадим подкласс UITabBarController и дадим ему свойства для любой информации , которой мы хотим поделиться между различными вкладками:

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

Теперь все наши контроллеры просмотра в контроллере панели вкладок могут получить доступ к этому свойству как таковому:

И, подклассировав UINavigationController таким же образом, мы можем использовать тот же подход для обмена данными во всем стеке навигации:

Есть несколько других сценариев. Этот ответ ни в коем случае не охватывает их все.

Какова наилучшая стратегия для данных,которые пользователь вводит в текстовое поле в контроллере представления, указанном здесь как 1, для отправки в контроллер представления 2? Эти два вида не связаны непосредственно сегментами. Следует ли это делать с помощью делегата? Если да,то какой объект.

я столкнулся с этим вопросом в интервью, я знаю, как обмениваться данными между двумя контроллерами, используя сервис, а также используя корневую область. Есть ли какой-либо способ сделать с in angular передачу данных между двумя контроллерами без использования службы и корневой области> Любые.

Этот вопрос возникает все время.

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

Читайте также:  Как получить нитрат алюминия 3 способами

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

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

(Другие альтернативы см. в ответе nhgrif ниже.)

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

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

Я создал демо-проект на GitHub, демонстрирующий, как вы можете это сделать. Вот ссылка:

SwiftDataContainerSingleton

Демонстрация использования контейнера данных singleton для сохранения состояния приложения и совместного использования его между объектами.

Класс DataContainerSingleton -это фактический singleton.

Он использует статическую константу sharedDataContainer для сохранения ссылки на singleton.

Чтобы получить доступ к singleton, используйте синтаксис

Пример проекта определяет 3 свойства в контейнере данных:

Чтобы загрузить свойство someInt из контейнера данных, вы должны использовать следующий код:

Чтобы сохранить значение в someInt, вы должны использовать синтаксис:

Метод DataContainerSingleton init добавляет наблюдателя для UIApplicationDidEnterBackgroundNotification . Этот код выглядит следующим образом:

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

Метод DataContainerSingleton init также пытается загрузить сохраненные значения для своих свойств.

Эта часть метода инициализации выглядит следующим образом:

Ключи для загрузки и сохранения значений в NSUserDefaults хранятся в виде строковых констант , которые являются частью структуры DefaultsKeys , определенной следующим образом:

Вы ссылаетесь на одну из этих констант следующим образом:

Использование контейнера данных singleton:

В этом примере приложения тривиально используется контейнер данных singleton.

Есть два контроллера вида. Первый-это пользовательский подкласс UIViewController ViewController , а второй — пользовательский подкласс UIViewController SecondVC .

Оба контроллера представления имеют текстовое поле на них, и оба загружают значение из свойства someInt контейнера данных singlelton в текстовое поле в своем методе viewWillAppear , и оба сохраняют текущее значение из текстового поля обратно в «someInt» контейнера данных.

Код для загрузки значения в текстовое поле находится в методе viewWillAppear: :

Код для сохранения отредактированного пользователем значения обратно в контейнер данных содержится в методах textFieldShouldEndEditing контроллеров представлений:

Вы должны загружать значения в свой пользовательский интерфейс в viewWillAppear, а не в viewDidLoad, чтобы ваш UI обновлялся каждый раз, когда отображается контроллер представления.

Swift 4

Существует так много подходов к передаче данных в swift. Здесь я добавляю некоторые из лучших подходов к этому.

1) Использование StoryBoard Segue

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

2) Использование Методов Делегирования

ViewControllerD

ViewControllerC

Другой альтернативой является использование центра уведомлений (NSNotificationCenter) и отправка уведомлений. Это очень слабая связь. Отправителю уведомления не нужно знать или заботиться о том, кто его слушает. Он просто публикует уведомление и забывает об этом.

Уведомления хороши для передачи сообщений one-to-many, так как может быть произвольное количество наблюдателей, прослушивающих данное сообщение.

Вместо создания контроллера данных singelton я бы предложил создать экземпляр контроллера данных и передать его по кругу. Для поддержки внедрения зависимостей я бы сначала создал протокол DataController :

Затем я бы создал класс SpecificDataController (или любое другое имя, которое в данный момент было бы подходящим) :

Класс ViewController должен иметь поле для хранения dataController . Обратите внимание, что тип dataController -это протокол DataController . Таким образом, легко переключать реализации контроллера данных:

В AppDelegate мы можем установить viewController в dataController :

Когда мы перейдем на другой viewController, мы сможем передать dataController в:

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

Читайте также:  Гольф лучший способ испортить хорошую прогулку кто сказал

Это, конечно, излишне, если мы просто хотим передать одно значение. В этом случае лучше всего согласиться с ответом nhgrif.

При таком подходе мы можем отделить представление от логической части.

Как указал @nhgrif в своем превосходном ответе, существует множество различных способов, которыми VCs (контроллеры представления) и другие объекты могут взаимодействовать друг с другом.

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

ответ nhrif позволяет отправлять информацию непосредственно из источника в пункт назначения VC. Как я уже упоминал в ответе, также можно отправлять сообщения обратно из пункта назначения в источник.

Фактически, вы можете настроить активный односторонний или двусторонний канал между различными контроллерами просмотра. Если контроллеры представлений связаны через сегмент раскадровки, время для настройки ссылок находится в методе prepareFor Segue.

У меня есть пример проекта на Github, который использует родительский контроллер представления для размещения 2 различных представлений таблиц в качестве дочерних. Дочерние контроллеры представления связаны с помощью сегментов встраивания, а родительский контроллер представления устанавливает 2-сторонние связи с каждым контроллером представления в методе prepareForSegue.

Вы можете найти этот проект на github (ссылка). Однако я написал его в Objective-C и не преобразовал его в Swift, поэтому, если вам неудобно в Objective-C, вам может быть немного трудно следовать

Если у вас есть раскадровка с идентифицированными сегментами, используйте:

Хотя если вы делаете все программно, включая навигацию между различными UIViewControllers, то используйте метод:

Примечание: чтобы использовать второй способ, вам нужно сделать свой UINavigationController, вы нажимаете UIViewControllers на делегат, и он должен соответствовать протоколу UINavigationControllerDelegate:

Это зависит от того, когда вы хотите получить данные.

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

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

Похожие вопросы:

В нашем случае у нас есть функция поиска в нашем приложении, которая показывает результаты поиска после ввода поискового запроса. Результаты поиска в нашем случае являются продуктами. Когда мы.

Я много читал о том, как перемещать данные между контроллерами представления в программировании Swift iOS, но до сих пор не нашел большого консенсуса: Временные модели (ненужные, я думаю, для.

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

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

Мне было интересно, как я могу поделиться объектами NSDictionary между несколькими контроллерами представления, которые в основном являются вкладками в моем приложении. Я попробовал использовать.

Какова наилучшая стратегия для данных,которые пользователь вводит в текстовое поле в контроллере представления, указанном здесь как 1, для отправки в контроллер представления 2? Эти два вида не.

я столкнулся с этим вопросом в интервью, я знаю, как обмениваться данными между двумя контроллерами, используя сервис, а также используя корневую область. Есть ли какой-либо способ сделать с in.

Я создаю компонент A-Frame и хочу обмениваться данными между такими функциями, как init и другими обработчиками пользовательских компонентов. Я выяснил, как добавить в схему компонента, чтобы.

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

Экспериментируя с контроллерами вида в Swift 4, различные поиски показывают, что существует несколько различных методов перемещения между контроллерами вида. Я впервые начинаю использовать этот код.

Источник

Оцените статью
Разные способы