【问题标题】:delegation and passing data back from childViewController委托并从 childViewController 传回数据
【发布时间】:2016-05-01 05:29:54
【问题描述】:

我已经为此苦苦挣扎了几天,并在途中得到了 S.O. 的宝贵帮助。我做了一个最简单的项目来减少它是一个错字的可能性。 我的所有项目都是一个 ViewController,它包含一个连接到 childViewController 的容器视图。 “父” ViewController 被设置为 childViewController 的委托。在孩子的 viewDidLoad 中,我传递的值只是一个字符串。此字符串应传递给父级并打印在控制台上。这是文件。

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

我认为当应用程序启动时,控制台应该记录以下消息是否正确:“这是我的值:你好”。我在逻辑上没有获得授权方面做错了什么,还是只是某个地方的愚蠢错字?交易

【问题讨论】:

    标签: objective-c delegation childviewcontroller parentviewcontroller


    【解决方案1】:

    您假设在实例化视图控制器时加载了视图。这就是它现在的工作方式。视图会在需要时加载(例如添加到父视图)。

    但您可以强制加载视图并使其正常工作。在设置委托后立即在子视图控制器上调用-loadViewIfNeeded。这可能会让你得到你想要的:

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

    或者,如果您确实想回调viewDidLoad 中的委托,那么您需要将NSLog 移动到-passValue: 方法,因为主视图控制器的viewDidLoad 方法已经完成正在运行。

    【讨论】:

    • [控制器 loadViewIfNeeded];正在使应用程序崩溃。我不完全理解的是“theValue”如何接收任何东西。如果它是像其他方法一样的方法,我不应该像这样在 viewDidLoad 中调用它吗:[self passValue:] 事情是我不想在那里传递参数,我想要 theValue。这个问题有意义吗?
    【解决方案2】:

    为此,请让 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 推送到导航堆栈之前,我们需要做的最后一件事是告诉 ChildController ParentController 是它的委托。

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

    【讨论】:

    • 您好,谢谢您,我正在按照您的指示进行操作。我对最后一行有同样的问题。 "ChildController *ChildController = [[ChildController alloc] initWithNib:@"ChildController" bundle:nil];"
    • 返回错误:“ChildController”没有可见的@interface声明选择器'initWithNib:bundle:'
    • 不要用 nib 初始化....试试这个,而 nib 仅在您有 nib 文件时使用...现在我想您正在使用情节提要...为此只需使用 init . ChildController *ChildController = [[ChildController alloc] init];
    猜你喜欢
    • 2016-05-01
    • 1970-01-01
    • 2013-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多