- Передача данных между контроллерами в Swift
- О Свифт
- Об этом уроке
- Настройка проекта XCode
- Подключение видов к файлам .swift
- Давайте код!
- Как Вы делитесь данными между контроллерами представлений и другими объектами в Swift?
- 8 ответов
- SwiftDataContainerSingleton
- Использование контейнера данных singleton:
- Похожие вопросы:
Передача данных между контроллерами в 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: объект, который создается один и только один раз в жизни вашего приложения и сохраняется в течение всего срока службы вашего приложения.
Этот подход хорошо подходит для ситуации, когда у вас есть глобальные данные приложения, которые должны быть доступны/изменяемы в разных классах вашего приложения.
Другие подходы, такие как настройка односторонних или двухсторонних связей между контроллерами представлений, лучше подходят для ситуаций, когда вы передаете информацию/сообщения непосредственно между контроллерами представлений.
(Другие альтернативы см. в ответе 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, различные поиски показывают, что существует несколько различных методов перемещения между контроллерами вида. Я впервые начинаю использовать этот код.
Источник