как получить доступ к предыдущим элементам представления в UINavigationController - PullRequest
2 голосов
/ 14 февраля 2012

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

Просмотр A myLabel.text = @ "first view";

(пользователь переходит к просмотру B)

Просмотр B (пользователь ввел сообщение,что мне нужно отобразить в представлении А) что-то вроде ViewA.myLabel.text = @ "сообщение, введенное пользователем"

Я пробовал много вещей, но не смог найти ничего очень полезного.Пожалуйста, помогите ..

Я использую Xcode 4 без ARC и без раскадровки.

Спасибо Сэм


Отредактировано:

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

ViewA *myView = [[ViewA alloc] init];
myView.title = @"View B" ;
myView.tableView.tag = 3;
myView.myTextView.text = @"Some Text";
[self.navigationController pushViewController:myView animated:YES];
[myView release];

Есть ли способ передать эти значения в свойства ViewController из ViewA, одновременно вызывая ViewB и возвращаясь обратно в ViewA?

Фактический сценарий выглядит следующим образом: пользователь получает и возможность написать сообщение в textView, или он может использовать предопределенные шаблоны.Если он нажимает кнопку «Шаблоны», он попадает в список предварительно определенных шаблонов, где он может выбрать любое из предварительно определенных сообщений.Теперь я хочу, чтобы, когда пользователь нажимал на любое из предопределенных сообщений, представление, содержащее список предопределенных сообщений, извлекалось, и выбранное сообщение автоматически заполнялось в textView основного представления.Каков наилучший подход для достижения этой цели?

TIA Sam

Ответы [ 3 ]

1 голос
/ 14 февраля 2012

Вы должны установить свой AViewController в качестве делегата вашего BViewController, чтобы вы могли отправить его обратно после определенного события. Использование делегата также позволит лучше отделить ваши ViewControllers.

В вашем BViewController определите протокол следующим образом:

BViewController.h:

@protocol BViewControllerDelegate <NSObject>
- (void)viewB:(UIViewController *)didEnterMessage:(NSString *)message;
@end

и добавьте свойство делегата:

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

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

- (IBAction)messageEntered {
  if ([self.delegate respondsToSelector:@selector(viewB:didEnterMessage:)]) {
    [self.delegate viewB:self didEnterMessage:self.yourTextField.text];
  }
}

Ваш AViewController должен реализовывать протокол BViewControllerDelegate следующим образом:

AViewController.h:

@interface AViewController <BViewControllerDelegate>

Когда ваш AViewController создает BViewController, он должен установить себя в качестве своего делегата перед его представлением. Может выглядеть так:

BViewController *bvc = [[BViewController alloc] init…];
bvc.delegate = self;

И, наконец, ваш AViewController должен реализовать viewB: didEnterMessage: method:

- (void)viewB:(UIViewController *)didEnterMessage:(NSString *)message {
  self.myLabel.text = message;
}

Это самый чистый способ сделать это, ИМХО.

1 голос
/ 14 февраля 2012

Вы можете получить свойство viewControllers контроллера навигации и использовать его, возможно, так:

UILabel *label = ((SomeViewController *)[self.navigationController.viewControllers objectAtIndex:1]).myLabel;

Однако это не надежно. Поскольку «предыдущий» вид за пределами экрана, система может выгрузить его, чтобы освободить память. Тогда label будет nil.

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

Но на самом деле это пахнет плохим дизайном. Вы почти никогда не должны пытаться получить доступ к представлениям контроллера представления, когда представление этого контроллера представления не на экране. Помните, как система может выгрузить представление контроллера представления, если представление находится вне экрана? Если некоторые UILabel в этом представлении содержали единственную копию важных данных, эти данные теперь исчезли!

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

EDIT

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

Я предполагаю, что ваш ViewA создает и толкает ViewB. Таким образом, вы должны присвоить ViewB свойство типа ViewA, например:

@class ViewA;  // forward declaration to avoid circular imports

@interface ViewB

@property (weak, nonatomic) ViewA *aView;

Затем, когда ваш ViewA создает экземпляр ViewB, вы устанавливаете свойство aView:

@implementation ViewA

- (void)pushViewB {
    ViewB *bView = [[ViewB alloc] init];
    bView.aView = self;
    [self.navigationController pushViewController:bView animated:YES];
}

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

0 голосов
/ 14 февраля 2012

Если вы хотите написать хороший код, вы должны следовать шаблону Model-View-Controller. Вот довольно хороший учебник http://www.cocoalab.com/?q=node/24 В двух словах это означает, что вы не должны хранить данные в View (а также view не должен выступать в качестве контроллера). Я предлагаю вам написать собственный класс, который будет выполнять это управление (хранить данные и передавать их из одного представления в другое). Если это просто тестовое приложение, вы можете использовать свойство viewControllers UINavigationController для доступа к контроллерам, которые находятся в стеке навигации, или просто создать переменную для хранения этих данных, например, в View B

- (void)textFieldDidEndEditing:(UITextField *)textField {
    stringToDisplayInFirstController = textField.text;
    NSArray * arrayOfControllers =  self.navigationController.viewControllers;
    UIViewController * viewControllerA = [arrayOfControllers objectAtIndex:[arrayOfControllers count]-1];
    viewControllerA.label.text = stringToDisplayInFirstController;

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