-1

Я боролся с этим в течение нескольких дней и получил ценную помощь на пути от S.O. Я сделал простейший возможный проект, чтобы уменьшить возможности его опечатки. Весь мой проект - это ViewController, который содержит контейнерный вид, подключенный к childViewController. «Родительский» ViewController устанавливается как делегат childViewController. В viewDidLoad для ребенка я передаю значение, которое является просто строкой. Эта строка должна быть передана родительскому устройству и напечатана на консоли. Вот файлы.делегирование и передача данных назад от childViewController

ViewController.h

#import <UIKit/UIKit.h> 
#import "ChildViewController.h" 

@interface ViewController : UIViewController <ChildViewControllerDelegate> 

@end 

ViewController.m

#import "ViewController.h" 

@interface ViewController() 

@property NSString *myValueRetrieved; 

@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    ChildViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"ChildVC"]; 

    controller.delegate = self; 

    NSLog(@"Here is my value: %@",self.myValueRetrieved); 
} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
} 

- (void) passValue:(NSString *)theValue{ 

    self.myValueRetrieved = theValue; 
} 

@end 

ChildViewController.h

#import <UIKit/UIKit.h> 

@protocol ChildViewControllerDelegate; 

@interface ChildViewController : UIViewController 

@property (weak)id <ChildViewControllerDelegate> delegate; 

@end 

@protocol ChildViewControllerDelegate <NSObject> 

- (void) passValue:(NSString*) theValue; 

@end 

ChildViewController.m

#import "ChildViewController.h" 

@interface ChildViewController() 
@property NSArray *colors; 
@end 

@implementation ChildViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    [self.delegate passValue:@"Hello"]; 
} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
} 

@end 

Могу ли я подумать, что при запуске приложения консоль должна зарегистрировать следующее сообщение: «вот моя ценность: привет». Я делаю что-то неправильно с точки зрения логически не получая делегирования или это просто глупая опечатка где-то? tx

ответ

0

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

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

controller.delegate = self; 
[controller loadViewIfNeeded]; 
NSLog(@"Here is my value: %@",self.myValueRetrieved); 

Или, если вы хотите, чтобы перезвонить делегат в viewDidLoad, то вам было бы нужно переместить NSLog методы -passValue:, так как основной контроллер представления viewDidLoad метод уже будет завершен.

+0

[контроллер loadViewIfNeeded]; сбой приложения. То, что я не совсем понимаю, - это то, как «theValue» получает что-либо. Если это метод, подобный другим, не должен ли я называть его в viewDidLoad следующим образом: [self passValue:] вещь в том, что я не хочу передавать аргумент там, я хочу theValue. Вопрос имеет смысл? – Paul

0

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

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

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

@class ChildController; 

@protocol ViewControllerBDelegate <NSObject> 
- (void)addItemViewController:(ChildController *)controller didFinishEnteringItem:(NSString *)item; 
@end 

рядом еще в ChildController.h вам нужно настроить свойство делегата и синтезировать в ChildController.h

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

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

NSString *itemToPassBack = @"Pass this value back to ParentController"; 
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack]; 

Это все для ChildController. Теперь в ParentController.h скажите ParentViewController импортировать Child и соответствовать его протоколу.

импорт "ChildController.h"

@interface ParentController: UIViewController В ParentController.m реализовать следующий метод из нашего протокола

- (void)addItemViewController:(ChildController *)controller didFinishEnteringItem:(NSString *)item 
{ 
    NSLog(@"This was returned from ChildController %@",item); 
} 

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

ChildController *ChildController = [[ChildController alloc] initWithNib:@"ChildController" bundle:nil]; 
ChildController.delegate = self 
[[self navigationController] pushViewController:ChildController animated:YES]; 
+0

Привет, Спасибо за это, я следую вашим инструкциям. У меня такая же проблема с последней строкой. "ChildController * ChildController = [[ChildController alloc] initWithNib: @" ChildController "bundle: nil];" – Paul

+0

Это возвращает ошибку: нет видимого @interface для «ChildController» объявляет селектор «initWithNib: bundle: ' – Paul

+0

не инициализируйте с помощью nib .... просто попробуйте это вместо nib используется только тогда, когда у вас есть файл nib. прямо сейчас я предполагаю, что вы используете раскадровки ... для этого просто используйте init. 'ChildController * ChildController = [[ChildController alloc] init];' – Shravan

Смежные вопросы