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

Этот поток сделал меня freak, так как мы используем колонки TIMESTAMP с On UPDATE CURRENT_TIMESTAMP (т. е. recordTimestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP) для отслеживания измененных записей и ETL в хранилище данных.

В случае, если кому-то интересно, в этом case TIMESTAMP ведут себя правильно, и вы можете различать две аналогичные даты, преобразуя TIMESTAMP в временную метку unix:

select TestFact.*, UNIX_TIMESTAMP(recordTimestamp) from TestFact;

id  recordTimestamp         UNIX_TIMESTAMP(recordTimestamp)
1   2012-11-04 01:00:10.0   1352005210
2   2012-11-04 01:00:10.0   1352008810
1309
задан swiftBoy 18 May 2019 в 06:16
поделиться

23 ответа

Этот вопрос, кажется, очень популярен здесь, на stackoverflow, поэтому я подумал, что постараюсь дать лучший ответ, чтобы помочь людям, начинающим в мире iOS, как я.

Я надеюсь, что этот ответ достаточно ясен для понимания людьми, и я ничего не пропустил.

Передача данных вперед

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

Для этого примера у нас будет ViewControllerA и ViewControllerB

Чтобы передать значение BOOL из ViewControllerA в ViewControllerB, мы сделаем следующее.

  1. в ViewControllerB.h создайте свойство для BOOL

    @property (nonatomic, assign) BOOL isSomethingEnabled;
    
  2. в ViewControllerA, вам нужно рассказать ему о ViewControllerB так используйте

    #import "ViewControllerB.h"
    

    Тогда, где вы хотите загрузить вид, например. didSelectRowAtIndex или еще что-нибудь IBAction, вам нужно установить свойство в ViewControllerB, прежде чем помещать его в стек навигации.

    ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
    viewControllerB.isSomethingEnabled = YES;
    [self pushViewController:viewControllerB animated:YES];
    

    Это установит isSomethingEnabled в ViewControllerB в BOOL значение YES.

Передача данных с использованием сегментов

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

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

. Таким образом, чтобы передать BOOL из ViewControllerA в ViewControllerB, мы бы сделайте следующее:

  1. в ViewControllerB.h создайте свойство для BOOL

    @property (nonatomic, assign) BOOL isSomethingEnabled;
    
  2. в ViewControllerA, которое вам нужно расскажите о ViewControllerB, поэтому используйте

    #import "ViewControllerB.h"
    
  3. Создайте переход от ViewControllerA до ViewControllerB на раскадровке и дайте ему идентификатор, в этом примере мы Я назову его "showDetailSegue"

  4. Далее нам нужно добавить метод к ViewControllerA, который вызывается при выполнении любого перехода, из-за этого нам нужно определить, какой вызов был вызван а затем сделай что-нибудь В нашем примере мы проверим "showDetailSegue", и если это будет выполнено, мы передадим наше значение BOOL в ViewControllerB

    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
        if([segue.identifier isEqualToString:@"showDetailSegue"]){
            ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController;
            controller.isSomethingEnabled = YES;
        }
    }
    

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

    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
        if([segue.identifier isEqualToString:@"showDetailSegue"]){
            UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
            ViewControllerB *controller = (ViewControllerB *)navController.topViewController;
            controller.isSomethingEnabled = YES;
        }
    }
    

    Это установит isSomethingEnabled в ViewControllerB значение BOOL YES.

Передача данных назад

Для передачи данных из ViewControllerB в ViewControllerA необходимо использовать Протоколы и делегаты или Блоки , последний может быть использован как слабосвязанный механизм для обратных вызовов.

Для этого мы сделаем ViewControllerA делегатом ViewControllerB. Это позволяет ViewControllerB отправлять сообщение обратно ViewControllerA, что позволяет нам отправлять данные обратно.

Чтобы ViewControllerA был делегатом ViewControllerB, он должен соответствовать протоколу ViewControllerB, который мы должны указать. Это сообщает ViewControllerA, какие методы он должен реализовать.

  1. В ViewControllerB.h ниже #import, но выше @interface вы указываете протокол.

    @class ViewControllerB;
    
    @protocol ViewControllerBDelegate <NSObject>
    - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
    @end
    
  2. затем еще в ViewControllerB.h вам нужно установить свойство delegate и синтезировать в ViewControllerB.m

    @property (nonatomic, weak) id <ViewControllerBDelegate> delegate;
    
  3. В ViewControllerB мы вызываем сообщение на delegate, когда открываем контроллер представления.

    NSString *itemToPassBack = @"Pass this value back to ViewControllerA";
    [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
    
  4. Вот и все для ViewControllerB. Теперь в ViewControllerA.h, скажите ViewControllerA импортировать ViewControllerB и соответствовать его протоколу.

    #import "ViewControllerB.h"
    
    @interface ViewControllerA : UIViewController <ViewControllerBDelegate>
    
  5. В ViewControllerA.m реализовать следующий метод из нашего протокола

    - (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
    {
        NSLog(@"This was returned from ViewControllerB %@",item);
    }
    
  6. Перед тем как отправить viewControllerB в стек навигации, нам нужно сообщить ViewControllerB, что ViewControllerA является его делегатом, в противном случае мы получим ошибку.

    ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
    viewControllerB.delegate = self
    [[self navigationController] pushViewController:viewControllerB animated:YES];
    

Ссылки

  1. Использование делегирования для связи с другими контроллерами представления в Руководство по программированию контроллера представления ]
  2. Шаблон делегата

Центр уведомлений NSN Это еще один способ передачи данных.

// add observer in controller(s) where you want to receive data
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeepLinking:) name:@"handleDeepLinking" object:nil];

-(void) handleDeepLinking:(NSNotification *) notification {
    id someObject = notification.object // some custom object that was passed with notification fire.
}

// post notification
id someObject;
[NSNotificationCenter.defaultCenter postNotificationName:@"handleDeepLinking" object:someObject];

Передача данных обратно из одного класса в другой (классом может быть любой контроллер, менеджер сети / сеанса, подкласс UIView или любой другой класс)

Блоки являются анонимными функциями.

Этот пример передает данные от Контроллера B к Контроллеру A

определяют блок

@property void(^selectedVoucherBlock)(NSString *); // in ContollerA.h

добавить обработчик блока (слушатель) , где вам нужно значение (например, вам нужен ваш ответ API в ControllerA или вам нужны данные ContorllerB на A)

// in ContollerA.m

- (void)viewDidLoad {
    [super viewDidLoad];
    __unsafe_unretained typeof(self) weakSelf = self;
    self.selectedVoucherBlock = ^(NSString *voucher) {
        weakSelf->someLabel.text = voucher;
    };
}

Перейти к контроллеру B

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ControllerB *vc = [storyboard instantiateViewControllerWithIdentifier:@"ControllerB"];
vc.sourceVC = self;
    [self.navigationController pushViewController:vc animated:NO];

пожарный блок

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: 
(NSIndexPath *)indexPath {
    NSString *voucher = vouchersArray[indexPath.row];
    if (sourceVC.selectVoucherBlock) {
        sourceVC.selectVoucherBlock(voucher);
    }
    [self.navigationController popToViewController:sourceVC animated:YES];
}

Другой рабочий пример для блоков

1641
ответ дан Nilesh R Patel 18 May 2019 в 06:16
поделиться

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

Скажем, у нас есть viewControllers: ViewController и NewViewController.

в ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    IBOutlet UITextField *mytext1,*mytext2,*mytext3,*mytext4;
}

@property (nonatomic,retain) IBOutlet UITextField *mytext1,*mytext2,*mytext3,*mytext4;

-(IBAction)goToNextScreen:(id)sender;

@end

в ViewController.m

#import "ViewController.h"

#import "NewViewController.h"

@implementation ViewController
@synthesize mytext1,mytext2,mytext3,mytext4;

-(IBAction)goToNextScreen:(id)sender
{
    NSArray *arr = [NSArray arrayWithObjects:mytext1.text,mytext2.text,mytext3.text,mytext4.text, nil];


    NewViewController *newVc = [[NewViewController alloc] initWithNibName:@"NewViewController" bundle:nil];

    newVc.arrayList = arr;

    [self.navigationController pushViewController:newVc animated:YES];

}

В NewViewController.h

#import <UIKit/UIKit.h>

@interface NewViewController : UITableViewController
{
    NSArray *arrayList;

    NSString *name,*age,*dob,*mobile;

}

@property(nonatomic, retain)NSArray *arrayList;

@end

В NewViewController.m

#import "NewViewController.h"

#import "ViewController.h"

@implementation NewViewController
@synthesize arrayList;

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

    // Return the number of rows in the section.
    return [arrayList count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];      
    }
    // Configure the cell...
    cell.textLabel.text = [arrayList objectAtIndex:indexPath.row];
    return cell;


}

@end

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

9
ответ дан Sabs 18 May 2019 в 06:16
поделиться

Я видел много людей, которые усложняли это, используя метод didSelectRowAtPath. Я использую Core Data в моем примере.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    //this solution is for using Core Data
    YourCDEntityName * value = (YourCDEntityName *)[[self fetchedResultsController] objectAtIndexPath: indexPath];

    YourSecondViewController * details = [self.storyboard instantiateViewControllerWithIdentifier:@"nameOfYourSecondVC"];//make sure in storyboards you give your second VC an identifier

    //Make sure you declare your value in the second view controller
    details.selectedValue = value;

    //Now that you have said to pass value all you need to do is change views
    [self.navigationController pushViewController: details animated:YES];

}

4 строки кода внутри метода, и все готово.

8
ответ дан App Dev Guy 18 May 2019 в 06:16
поделиться

Существует 3 типа для передачи данных из одного ViewController в другой ViewController.

  1. Программно
  2. Segue
  3. UserDefaults

Ссылка на демонстрационный проект здесь - https: / /github.com/kamanijasmin13/Swift-Pass-data-between-viewcontrollers

Программно enter image description here

Segue enter image description here

UserDefaults enter image description here

Ссылка на демонстрационный проект здесь - https://github.com/kamanijasmin13/Swift-Pass-data-between-viewcontrollers

5
ответ дан Kamani Jasmin 18 May 2019 в 06:16
поделиться

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

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"myIdentifer]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        myViewController *destViewController = segue.destinationViewController;
        destViewController.name = [object objectAtIndex:indexPath.row];
    }
}
3
ответ дан crazy_tiger_corp 18 May 2019 в 06:16
поделиться

Я рекомендую блоки / замыкания и специальные конструкторы.

Предположим, вам нужно передать строку из FirstViewController в SecondViewController.

Ваш первый контроллер просмотра.

class FirstViewController : UIViewController {

    func moveToViewControllerB() {

        let second_screen = SecondViewController.screen(string: "DATA TO PASS", call_back: {
            [weak self] (updated_data) in
            ///This closure will be called by second view controller when it updates something
        })
        self.navigationController?.pushViewController(second_screen, animated: true)
    }


}

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

class SecondViewController : UIViewController {

    var incoming_string : String?
    var call_back : ((String) -> Void)?

    class func screen(string: String?, call_back : ((String) -> Void)?) -> SecondViewController {

        let me = SecondViewController(nibName: String(describing: self), bundle: Bundle.main);
        me.incoming_string = string
        me.call_back = call_back
        return me
    }

    // Suppose its called when you have to update FirstViewController with new data.
    func updatedSomething() {

        //Executing block that is implemented/assigned by the FirstViewController.
        self.call_back?("UPDATED DATA")
    }

}
1
ответ дан Umair 18 May 2019 в 06:16
поделиться

Я предпочитаю делать это без делегатов и сегментов. Это можно сделать с помощью пользовательского init или установив дополнительные значения.

1. Custom init

class ViewControllerA: UIViewController {
  func openViewControllerB() {
    let viewController = ViewControllerB(string: "Blabla", completionClosure: { success in
      print(success)
    })
    navigationController?.pushViewController(animated: true)
  }
}

class ViewControllerB: UIViewController {
  private let completionClosure: ((Bool) -> Void)
  init(string: String, completionClosure: ((Bool) -> Void)) {
    self.completionClosure = completionClosure
    super.init(nibName: nil, bundle: nil)
    title = string
  }

  func finishWork() {
    completionClosure()
  }
}

2. Факультативные переменные

class ViewControllerA: UIViewController {
  func openViewControllerB() {
    let viewController = ViewControllerB()
    viewController.string = "Blabla"
    viewController.completionClosure = { success in
      print(success)
    }
    navigationController?.pushViewController(animated: true)
  }
}

class ViewControllerB: UIViewController {
  var string: String? {
    didSet {
      title = string
    }
  }
  var completionClosure: ((Bool) -> Void)?

  func finishWork() {
    completionClosure?()
  }
}
1
ответ дан Timur Bernikovich 18 May 2019 в 06:16
поделиться

Используйте центр уведомлений для передачи данных из одного вида в другой. Шаблон слушателя-наблюдателя работает лучше всего. Другим обходным путем может быть создание одинаковых объектов в обоих классах. Создание объекта класса 2 в первом классе, доступ к объектам данных, которые необходимо передать, и их установка, а затем нажатие контроллера представления.

-4
ответ дан Jay Sampat 18 May 2019 в 06:16
поделиться

Создайте свойство на следующем view controller .h и определите геттер и сеттер.

Добавить это property в NextVC.h на nextVC

@property (strong, nonatomic) NSString *indexNumber;

Добавить

@synthesize indexNumber; в NextVC.m

И последний

NextVC *vc=[[NextVC alloc]init];

vc.indexNumber=@"123";

[self.navigationController vc animated:YES];
14
ответ дан Sport 18 May 2019 в 06:16
поделиться

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

Некоторое время назад я написал сообщение в блоге об этом: Совместное использование кода модели . Вот краткое резюме:

Общие данные

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

  • Итерация грубой силы на контроллерах представления (в контроллере навигации или панели вкладок) для установки данных
  • Установка данных в prepareForSegue (если раскадровки) или init (если программный)

Поскольку подготовка к переходу является наиболее распространенным, приведем пример:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    var next = segue.destinationViewController as NextViewController
    next.dataSource = dataSource
}

Независимый доступ

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

Наиболее распространенный способ, которым я видел это, - это одноэлементный экземпляр. Поэтому, если ваш одноэлементный объект был DataAccess, вы могли бы сделать следующее в методе viewDidLoad UIViewController:

func viewDidLoad() {
    super.viewDidLoad()
    var data = dataAccess.requestData()
}

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

  • Наблюдение значения ключа
  • NSNotification
  • Базовые данные
  • NSFetchedResultsController
  • Источник данных

Базовые данные

Приятно, что в Core Data есть обратные отношения. Поэтому, если вы хотите просто дать NotesViewController объект notes, вы можете это сделать, потому что он будет иметь обратную связь с чем-то другим, таким как блокнот. Если вам нужны данные на ноутбуке в NotesViewController, вы можете вернуться к графу объектов, выполнив следующие действия:

let notebookName = note.notebook.name

Подробнее об этом читайте в моем блоге: Совместное использование кода модели [1 125]

11
ответ дан Super Developers 18 May 2019 в 06:16
поделиться

Передача данных из ViewController 2 (назначение) в viewController 1 (Source) является более интересной вещью. Предполагая, что вы используете storyBoard, это все способы, которые я узнал:

  • Делегат
  • Уведомление
  • Пользователь по умолчанию
  • Singleton

Это уже обсуждалось здесь.

Я обнаружил, что есть еще несколько способов:

- Использование обратных вызовов блока:

использовать его в методе prepareForSegue в VC1

NextViewController *destinationVC = (NextViewController *) segue.destinationViewController;
[destinationVC setDidFinishUsingBlockCallback:^(NextViewController *destinationVC)
{
    self.blockLabel.text = destination.blockTextField.text;
}];

- Использование раскадровок Unwind (Exit)

Реализовать метод с аргументом UIStoryboardSegue в VC 1, например так:

-(IBAction)UnWindDone:(UIStoryboardSegue *)segue { }

В хуке storyBoard кнопка «возврат» к зеленой кнопке выхода (размотка) видеомагнитофона. Теперь у вас есть переход, который «возвращается», поэтому вы можете использовать свойство destinationViewController в prepareForSegue в VC2 и изменить любое свойство VC1, прежде чем оно вернется.

  • Еще один вариант использования раскадровок Undwind (Выход) - вы можете использовать метод, который вы написали в VC1

    -(IBAction)UnWindDone:(UIStoryboardSegue *)segue {
        NextViewController *nextViewController = segue.sourceViewController;
        self.unwindLabel.text = nextViewController.unwindPropertyPass;
    } 
    

    И в prepareForSegue из VC1 вы можете изменить любое свойство, которое вы хотите поделиться.

В обоих вариантах раскрутки вы можете установить свойство тега кнопки и проверить его в prepareForSegue.

Надеюсь, я что-то добавил к обсуждению.

:) Приветствия.

39
ответ дан Alexander Abakumov 18 May 2019 в 06:16
поделиться

NewsViewController

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  [tbl_View deselectRowAtIndexPath:indexPath animated:YES];
  News *newsObj = [newstitleArr objectAtIndex:indexPath.row];
  NewsDetailViewController *newsDetailView = [[NewsDetailViewController alloc] initWithNibName:@"NewsDetailViewController" bundle:nil];

  newsDetailView.newsHeadlineStr = newsObj.newsHeadline;

  [self.navigationController pushViewController:newsDetailView animated:YES];
}

NewsDetailViewController.h

@interface NewsDetailViewController : UIViewController
@property(nonatomic,retain) NSString *newsHeadlineStr;
@end

NewsDetailViewController.m

@synthesize newsHeadlineStr;
10
ответ дан Florent 18 May 2019 в 06:16
поделиться

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

Скажем, у нас есть viewControllers: viewControllerA и viewControllerB

Теперь в viewControllerB.h

@interface viewControllerB : UIViewController {

  NSString *string;
  NSArray *array;

}

- (id)initWithArray:(NSArray)a andString:(NSString)s;

В viewControllerB.m

#import "viewControllerB.h"

@implementation viewControllerB

- (id)initWithArray:(NSArray)a andString:(NSString)s {

   array = [[NSArray alloc] init];
   array = a;

   string = [[NSString alloc] init];
   string = s;

}

В viewControllerA.m

#import "viewControllerA.h"
#import "viewControllerB.h"

@implementation viewControllerA

- (void)someMethod {

  someArray = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
  someString = [NSString stringWithFormat:@"Hahahahaha"];

  viewControllerB *vc = [[viewControllerB alloc] initWithArray:someArray andString:someString];

  [self.navigationController pushViewController:vc animated:YES];
  [vc release];

}

Таким образом, вы можете передавать данные из viewControllerA в viewControllerB без установки какого-либо делегата. ;)

21
ответ дан Aniruddh Joshi 18 May 2019 в 06:16
поделиться

В моем случае я использовал одноэлементный класс, который может работать как глобальный объект, предоставляя доступ к данным практически из любого места в приложении. Первое, что нужно сделать - создать класс синглтона. Пожалуйста, обратитесь к странице: « Как должен выглядеть мой синглтон Objective C? » И что я сделал, чтобы сделать объект глобально доступным, просто импортировал его в appName_Prefix.pch, который предназначен для применения оператора import в каждом классы. Чтобы получить доступ к этому объекту и использовать его, я просто реализовал метод класса для возврата общего экземпляра, который содержит свои собственные переменные

18
ответ дан Community 18 May 2019 в 06:16
поделиться

Передача данных между FirstViewController в SecondViewController, как показано ниже

Например:

Значение FirstViewController String как

StrFirstValue = @"first";

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

1> Нам нужно создать строковый объект в файле SecondViewController.h

NSString *strValue;

2> Необходимо объявить свойство, как показано ниже в объявлении в файле .h

@property (strong, nonatomic)  NSString *strSecondValue;

3> Необходимо синтезировать это значение в файле FirstViewController.m ниже объявления заголовка

@synthesize strValue;

и в FirstViewController.h:

@property (strong, nonatomic)  NSString *strValue;

4> В FirstViewController Из какого метода мы переходим ко второму виду, пожалуйста, напишите ниже код в этом методе

SecondViewController *secondView= [[SecondViewController alloc]     
initWithNibName:@"SecondViewController " bundle:[NSBundle MainBundle]];

[secondView setStrSecondValue:StrFirstValue];

[self.navigationController pushViewController:secondView animated:YES ];
17
ответ дан SpyZip 18 May 2019 в 06:16
поделиться

В настоящее время я участвую в решении этой проблемы с открытым исходным кодом через проект MCViewFactory, который можно найти здесь:

https://github.com/YetiHQ/manticore-iosviewfactory

Идея состоит в том, чтобы подражать парадигме намерений Android, используя глобальную фабрику для управления видом, который вы просматриваете, и используя «намерения» для переключения и передачи данных между представлениями. Вся документация находится на странице github, но вот некоторые основные моменты:

Вы настраиваете все свои представления в файлах .XIB и регистрируете их в делегате приложения при инициализации фабрики.

// Register activities

MCViewFactory *factory = [MCViewFactory sharedFactory];

// the following two lines are optional. 
[factory registerView:@"YourSectionViewController"]; 

Теперь, в вашем VC, каждый раз, когда вы хотите перейти к новому VC и передать данные, вы создаете новое намерение и добавляете данные в его словарь (saveInstanceState). Затем просто установите текущее намерение фабрики:

MCIntent* intent = [MCIntent intentWithSectionName:@"YourSectionViewController"];
[intent setAnimationStyle:UIViewAnimationOptionTransitionFlipFromLeft];
[[intent savedInstanceState] setObject:@"someValue" forKey:@"yourKey"];
[[intent savedInstanceState] setObject:@"anotherValue" forKey:@"anotherKey"];
// ...
[[MCViewModel sharedModel] setCurrentSection:intent];

Все ваши представления, которые соответствуют этому, должны быть подклассами MCViewController, которые позволяют вам переопределить новый метод onResume:, позволяющий вам получить доступ к данные, которые вы передали.

-(void)onResume:(MCIntent *)intent {
    NSObject* someValue = [intent.savedInstanceState objectForKey:@"yourKey"];
    NSObject* anotherValue = [intent.savedInstanceState objectForKey:@"anotherKey"];

    // ...

    // ensure the following line is called, especially for MCSectionViewController
    [super onResume:intent];
}

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

17
ответ дан 18 May 2019 в 06:16
поделиться

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

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

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

Есть три части.

  1. Отправитель
  2. The Segue
  3. Получатель

Это очень простой макет представления с переходом между ними.


Very simple view layout.  Note : No navigation controller


Вот настройки для отправителя


The Sender


Вот настройка для приемника.


The Receiver


Наконец, установка для перехода.


The Segue Identifier


Контроллеры представления

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

Эта страница принимает изначально загруженное значение и передает его.

import UIKit


class ViewControllerSender: UIViewController {

    // THE STUFF - put some info into a variable
    let favoriteMovie = "Ghost Busters"

    override func viewDidAppear(animated: Bool) {
        // PASS IDENTIFIER - go to the recieving view controller.
        self.performSegueWithIdentifier("goToReciever", sender: self)
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        //GET REFERENCE - ...to the receiver view.
        var viewControllerReceiver = segue.destinationViewController as? ViewControllerReceiver

        //PASS STUFF - pass the variable along to the target.
        viewControllerReceiver!.yourFavMovie = self.favoriteMovie

    }

}

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

import UIKit

class ViewControllerReceiver: UIViewController {

    //Basic empty variable waiting for you to pass in your fantastic favorite movie.
    var yourFavMovie = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        //And now we can view it in the console.
        println("The Movie is \(self.yourFavMovie)")

    }   
}

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

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

Ghost Busters is a classic folks.

17
ответ дан Nirav Vasoya 18 May 2019 в 06:16
поделиться

Это не способ сделать это, вы должны использовать делегатов, я предполагаю, что у нас есть два контроллера представления ViewController1 и ViewController2, и этот элемент проверки находится в первом, и когда его состояние изменяется, вы хотите что-то сделать в ViewController2, чтобы добиться этого надлежащим образом, вы должны сделать следующее:

Добавить новый файл в ваш проект (Протокол Objective-C) Файл -> Новый, теперь назовите его ViewController1Delegate или как хотите, и напишите они между директивами @interface и @end

@optional

- (void)checkStateDidChange:(BOOL)checked;

Теперь перейдите к ViewController2.h и добавьте

#import "ViewController1Delegate.h"

, затем измените его определение на

@interface ViewController2: UIViewController<ViewController1Delegate>

Теперь перейдите к ViewController2.m и внутри реализации добавьте:

- (void)checkStateDidChange:(BOOL)checked {
     if (checked) {
           // Do whatever you want here
           NSLog(@"Checked");
     }
     else {
           // Also do whatever you want here
           NSLog(@"Not checked");
     }
}

Теперь перейдите к ViewController1.h и добавьте следующее свойство:

@property (weak, nonatomic) id<ViewController1Delegate> delegate; 

Теперь, если вы создаете ViewController1 внутри ViewController2 после какое-то событие, то вы должны сделать это таким образом, используя файлы NIB:

ViewController1* controller = [[NSBundle mainBundle] loadNibNamed:@"ViewController1" owner:self options:nil][0];
controller.delegate = self;
[self presentViewController:controller animated:YES completion:nil];

Теперь все готово, когда вы обнаруживаете событие проверки, измененное в V iewController1, все, что вам нужно сделать, это ниже

[delegate checkStateDidChange:checked]; // You pass here YES or NO based on the check state of your control

Пожалуйста, скажите мне, если есть что-то, что не ясно, если я не правильно понял ваш вопрос.

22
ответ дан Boda Taljo 18 May 2019 в 06:16
поделиться

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

1- As working with setter and getter method like in viewController.h
   @property (retain, nonatomic) NSString *str;
   now, in viewController.m
   @synthesize str;


   here i have pdf url and segue to another viewController like this and pdfObject is my pdfModel basicilly is NSOBJECT class.  

   str =[NSString stringWithFormat:@"%@",pdfObject.objPath];
NSLog(@"pdfUrl :***: %@ :***:",pdfUrl);

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

прагма - Навигация

  // In a storyboard-based application, you will often want to do a little preparation before navigation

 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if ([[segue identifier] isEqualToString:@"programPDFViewController_segue"]){
    programPDFViewController *pdfVC = [segue destinationViewController];
    [pdfVC setRecievedPdfUrl:str];

   }
 }

Теперь успешно я получил строку URL-адреса в формате PDF и другой ViewController и использовать эту строку в веб-просмотре ...

2- При работе с такими делегатами у меня есть один класс утилит NSObject, содержащий мои методы dateFormatter, sharedInstance, EscapeWhiteSpaceCharacters, convertImageToGrayScale и другие методы, с которыми я работал на протяжении всего процесса. application, теперь в utilities.h

. В этом случае вам не нужно создавать переменные при постоянном анализе данных от одного к другому контроллеру представления один раз, когда ваша созданная строковая переменная в utilities.h просто делает его равным nil; и снова использовался

  @interface Utilities : NSObject

  Utilities.h
 +(Utilities*)sharedInstance;

 @property(nonatomic,retain)NSString* strUrl;

, теперь в утилитах.m

   @implementation utilities


  +(utilities*)sharedInstance
  {
  static utilities* sharedObj = nil;
  if (sharedObj == nil) {
    sharedObj = [[utilities alloc] init];
    }
   return sharedObj;
  }

now its done come to your firstViewController.m and call delegate

NSString*str =[NSString stringWithFormat:@"%@",pdfObject.objPath];

[Connection sharedInstance].strUrl=nil;
[Connection sharedInstance].strUrl=str;

 Now go to you secondViewController.m directly use it without creating variable 

 in viewwillapear what i did

 -(void)viewWillAppear:(BOOL)animated{
     [super viewWillAppear:YES];

   [self webViewMethod:[Connection sharedInstance].strUrl];

 }


 -(void)WebViewMethod:(NSString)Url{

 // working with webview enjoy coding :D

 }

эта работа делегата надежна с управлением памятью

2
ответ дан Nayab Khan 18 May 2019 в 06:16
поделиться

После дополнительных исследований выяснилось, что протоколы и делегаты - правильный путь / Apple предпочитает делать это.

В конечном итоге я использовал этот пример

Обмен данными между контроллерами представления и другими объектами @ iPhone Dev SDK

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

Спасибо за вашу помощь.

83
ответ дан Jason Whitehorn 18 May 2019 в 06:16
поделиться

M в MVC предназначен для «Модели», а в парадигме MVC роль классов моделей заключается в управлении данными программы. Модель является противоположностью представления - представление знает, как отображать данные, но ничего не знает о том, что делать с данными, тогда как модель знает все о том, как работать с данными, но ничего о том, как их отображать. Модели могут быть сложными, но это не обязательно - модель для вашего приложения может быть такой же простой, как массив строк или словарей.

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

131
ответ дан Caleb 18 May 2019 в 06:16
поделиться

Если вы хотите передать данные с одного контроллера на другой, попробуйте этот код

FirstViewController.h

@property (nonatomic, retain) NSString *str;

SecondViewController.h

@property (nonatomic, retain) NSString *str1;

FirstViewController.m

- (void)viewDidLoad
   {
     // message for the second SecondViewController
     self.str = @"text message";

     [super viewDidLoad];
   }

-(IBAction)ButtonClicked
 {
   SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
   secondViewController.str1 = str;
  [self.navigationController pushViewController:secondViewController animated:YES];
 }
28
ответ дан RckLN 18 May 2019 в 06:16
поделиться

Поскольку SwiftUI

Думает о @EnvironmentObject как о более умном, более простом способе использовать @ObservedObject на большом количестве представлений. Вместо того, чтобы создавать некоторые данные в поле зрения A, затем передавая его представлению B, затем представлению C, затем представлению D прежде наконец использовать его, можно создать его в поле зрения и поместить его в среду так, чтобы представления B, C, и D автоматически имели доступ к нему.

Примечание: объекты Среды должны быть предоставлены представлением †предка “, если SwiftUI can’t находит, что объект среды корректного типа you’ll получает катастрофический отказ. Это запрашивает предварительные просмотры также, так быть осторожным.

Как пример, here’s заметный объект, который хранит пользовательские настройки:

class UserSettings: ObservableObject {
@Published var score = 0

}

0
ответ дан 19 December 2019 в 20:14
поделиться