Подтвердить что ты не робот

Передача данных между контроллерами View с использованием Segue

Я новичок в iOS. Я столкнулся с проблемой передачи данных между ViewControllers. У меня есть три viewControllers (view_1, view_2 и view_3).

Здесь моя настройка: -

  • Выберите view_1
  • нажимает view_2
  • нажимает view_3

Я хочу отправить ссылку ViewController (id) из 'view_1' в 'view_3'. поэтому я включаю include "view_3" в 'view_1' и устанавливаю значение в переменную 'view_3' (используя view_3 *v3=[[view_3 alloc] init ]; v3.reference=self;). В консоли отображается:

просмотр контроллера: -; < ViewController: 0x89e9540 >

в "view_1", но в "view_3", на консоли он показывает

view controller (null)

Но когда я использовал 'view_2' для передачи этих данных свою работу. Но как? Я хочу знать это поведение, и есть ли какое-либо решение для его создания?

пожалуйста, помогите.

4b9b3361

Ответ 1

"Передача данных в контроллер назначения" при срабатывании segue будет достигнута путем переопределения метода prepareForSegue:sender:.

Как правило, вы передаете данные и НЕ контроллер представления источника, в контроллер представления назначения. "данные" могут быть определенным аспектом вашего приложения "модель". Это объект, например "Пользователь", или, возможно, массив, содержащий "Пользователь" и т.д.

Контроллер представления назначения не должен знать о контроллере представления источника. Это означает, что контроллеру вида назначения не нужно импортировать заголовок контроллера представления источника.

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

Смотрите: Настройка целевого контроллера при запуске Segue

Если вам нужен какой-то "протокол связи" между источником и получателем, вы можете использовать делегирование для связи с другими контроллерами представлений. Это включает определение @protocol (например, наличие метода doneButton) и свойство delegate, которое определено в контроллере представления назначения. Протокол должен быть определен в заголовке контроллера представления назначения, если он определен для контроллера представления назначения. Обычно вы определяете протокол с точки зрения контроллера назначения, а не от требований источника.

Контроллер представления источника затем создает делегат (если только он сам он уже есть) и устанавливает delegate контроллера точки назначения. Контроллер представления назначения отправляет делегат-методы делегату, и делегат обрабатывает его.

Теперь передача данных из VC_A в VC_B должна быть прямой. Вы должны прочитать несколько примеров, которые используют prepareForSegue:sender:. Например, контроллер представления назначения может иметь свойство data, которое представляет собой предмет, который он должен отображать. Контроллер представления источника должен установить это свойство в prepareForSegue:sender:.

Передача данных с VC_A через VC_B на VC_C также должна быть прямой.

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


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

У вас может быть модель приложения, которая является глобальной. Предположим, ваша "модель приложения" является объектом типа Document. Предположим, что в любой момент есть только один экземпляр этой модели приложения. Затем модель представляет собой "Singleton", к которой можно получить доступ из любого места в вашем приложении, например:

Document* document = [Document sharedDocument];

Однако предпочтительный способ получить экземпляр модели находится в первом контроллере представления, который требует доступа к нему, в этом случае: VC_A.

Затем VC_A передает экземпляр Document в следующий контроллер VC_B просмотра. И VC_B передает объект документа в VC_C.

Вы должны прочитать официальную документацию "Просмотреть руководство по программированию контроллера iOS.


Пример 1

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

Контроллер табличного представления будет иметь свойство "data" users:

В UsersTableViewController.h:

@interface UsersTableViewController : UIViewController
@property (nonatomic, readonly) NSArray* users;
@end

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

Массив "users" - это данные табличного представления, которые должны отображаться в строках. Каждая строка показывает "резюме" пользователя.

Более подробная информация о пользователе должна отображаться в контроллере подробного представления. Данные контроллера подробного представления представляют собой один пользователь типа user.

Когда пользователь наберет определенную строку в представлении таблицы, отобразится контроллер подробного представления. Перед тем, как он будет отображаться, контроллер табличного представления должен сконфигурировать контроллер подробного представления: контроллер табличного представления назначает контроллеру подробного представления "свойство данных" текущего выбранного пользователя. Таким образом, контроллер подробного представления должен иметь общедоступное свойство user:

@interface UserViewController : UIViewController
@property (nonatomic) User* user;
@end

Контроллер табличного представления настраивает контроллер подробного представления в prepareForSegue:sender::

В UsersTableViewController.m

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"ShowUserDetails"]) {
        UserViewController* userViewController = [segue destinationViewController];
        userViewController.user = [self.users objectInListAtIndex:[self.tableView indexPathForSelectedRow].row];
    }
}

Пример 2

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

Предостережение:

Это не полный пример. Цель этого примера должна продемонстрировать, как использовать "делегирование". Полнофункциональная реализация задач данных, как показано в примере, потребует значительных усилий. В таких сценариях "Делегация" будет наиболее предпочтительным подходом к выполнению этого (ИМХО).

Предположим, что мы хотим

  • Показать пользователя
  • Изменить (изменить) пользователя
  • Создать нового пользователя и
  • Удалить пользователя

из подробного представления.

Эти "задачи данных" не должны выполняться самим контроллером подробного представления, вместо этого ответственный за эти задачи данных отвечает делегат.

Эти действия данных обрабатываются делегатом:

@protocol UserDataSourceDelegateProtocol <NSObject>
- (User*) viewControllerUser:(UserViewControllerBase*)viewController;
- (void) viewController:(UserViewControllerBase*)viewController dismissWithUpdatedUser:(User*)user;
- (void) viewController:(UserViewControllerBase*)viewController dismissWithDeletedUser:(User*)user;
- (void) viewController:(UserViewControllerBase*)viewController dismissWithCreatedUser:(User*)user;
@end

Этот протокол отражает основные методы CRUD (создание, чтение, обновление, удаление).

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

Может быть несколько контроллеров подробных представлений, все подклассы абстрактного класса UserViewControllerBase, которые обрабатывают показ, редактируют и создают задачи. Удаление пользователя может выполняться в представлении таблицы и в контроллере представления "Показать пользователя" :

  • ShowUserViewController
  • EditUserViewController
  • NewUserViewController

Например, EditUserViewController отправит viewController:dismissWithUpdatedUser:, когда пользователь наберет кнопку "назад" И, если пользователь изменил объект пользователя. Теперь делегат может или не может отклонить подробный вид. Это может быть запрещено, например, при наличии ошибок проверки.

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

UserDataSourceDelegateProtocol может быть определен в дополнительном заголовке.

В UsersTableViewController.m:

#import "UserDataSourceDelegateProtocol.h"
#import "ShowUserViewController.h"


@interface UsersTableViewController () <UserDataSourceDelegateProtocol> 
@property (nonatomic, readonly) NSArray* users;
@end


// This delegate will be called when the detail view controller request 
// the user object which shall be displayed.
- (User*) viewControllerUser:(UserViewControllerBase*)viewController {
    return [self.users objectInListAtIndex:[self.tableView indexPathForSelectedRow].row];
}

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

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:UserShowSegueID])
    {
        ShowUserViewController* showViewController = segue.destinationViewController;
        showViewController.delegate = self; // Data Source Handler is self
    }
}

Контроллер вида "Редактировать пользователя" обычно является контроллером представления назначения контроллера "Показать пользователя" , который просматривается, когда пользователь нажимает кнопку "Изменить".

Контроллер вида "Показать пользователя" настроит делегата для Контроллер вида "Редактировать пользователя" получает один и тот же делегат:

В ShowUserViewController.m

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:UserEditSegueID])
    {
        EditUserViewController* editViewController = segue.destinationViewController;
        editViewController.delegate = self.delegate; // pass through the data source hanlder
    }
}

Делегат данных может обрабатывать обновленного пользователя следующим образом:

В UsersTableViewController.m:

- (void) viewController:(UserViewControllerBase*)viewController
 dismissWithUpdatedUser:(User*)user {
    if (/* is valid user and can be saved */) {
        [viewController.presentingViewController dismissViewControllerAnimated:YES
                                                                     completion:nil];
    }
}

Ответ 2

Этот проект Swift на YouTube помог мне наконец понять, как это сделать.

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

Настройка раскадровки

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

Это не очень сложно. Создайте раскладку в построителе интерфейса. Чтобы сделать segue, вы просто control нажмите на кнопку и перетащите ее на второй контроллер просмотра.

Контроллер первого взгляда

Код для первого вида контроллера -

import UIKit

class FirstViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    // This function is called before the segue
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        // get a reference to the second view controller
        let secondViewController = segue.destinationViewController as! SecondViewController

        // set a variable in the second view controller with the String to pass
        secondViewController.receivedString = textField.text!
    }

}

Второй контроллер просмотра

И код для второго контроллера просмотра

import UIKit

class SecondViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    // This variable will hold the data being passed from the First View Controller
    var receivedString = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        // Used the text from the First View Controller to set the label
        label.text = receivedString
    }

}

Не забывайте

  • Подключите выходы для UITextField и UILabel.
  • Установите первый и второй контроллеры просмотра в соответствующие файлы Swift в IB.

Процесс передачи данных на третий контроллер просмотра будет таким же.

Ответ 3

ya существует решение, но не самое правильное.

ViewController3.h

-(void)getUser:(NSString *)strPassedUser;

перейдите в ViewController3.m и выше @interface добавьте переменную типа

NSString *recievingVariable ;

а затем где-то внутри ViewController3.m

-(void)getUser:(NSString *)strPassedUser
{
    recievingVariable = strPassedUser;
}

ViewController1 и импортируйте ViewController3 то делай вот так..

ViewController3 * vc3 = [ViewController3 alloc]getUser :@"me"];

в этом случае вызывается функция getUser, и вы получите receivingVariable= me.

Ответ 4

Лучшее и легкое решение.

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"webView"];
webView = (WebViewController *)vc;
webView.strWebLink = @"http://www.Google.com/";
[self.navigationController showViewController:vc sender:self];

Ответ 5

Использовать шаблон Singleton:

Шаблон Singleton в разработке программного обеспечения представляет собой шаблон проектирования, который гарантирует, что класс имеет только один экземпляр и предоставляет глобальную точку доступа к нему.

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

Пример:

class Singleton {
    static let sharedInstance = Singleton()
    var studentId = 1281
}

И вы можете использовать его в любом месте своего приложения следующим образом:

var studentId = Singleton.sharedInstance.studentId
print("Student Id: \(studentId)")