【问题标题】:Understanding the mechanism when passing data back from a second view controller to main view controller了解将数据从第二个视图控制器传回主视图控制器时的机制
【发布时间】:2014-02-25 17:25:34
【问题描述】:

我目前正试图更好地理解控制器之间传递数据的机制是如何工作的,我有点困惑,尤其是当将数据从第二个视图控制器传递回主视图控制器时强>。

这是我有的,但不完全理解。我有两个视图控制器,在第一个中,我有一个按钮,当单击它时,它基本上会转到第二个视图控制器和一个显示从第二个视图控制器发送的消息的标签。在第二个视图控制器中,我有一个按钮和一个文本字段,该按钮基本上将文本字段中的任何内容发送到主视图控制器中的标签。

这里是代码...

// FirstVC.h

#import <UIKit/UIKit.h>
#import "SecondVC.h"
@interface FirstVC : UIViewController <passNames>

@property (nonatomic, strong) NSString* firstNameString;
@property (weak, nonatomic) IBOutlet UILabel *firstNameLabel;

@end

//FirstVC.m

#import "FirstVC.h"

@implementation FirstVC

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier]isEqualToString:@"secondController"])
    {
        UINavigationController *navController = segue.destinationViewController;
        SecondVC *vc2 =  (SecondVC*)navController.topViewController;
        [vc2 setDelegate:self];
    }
}
-(void)viewWillAppear:(BOOL)animated
{
    self.firstNameLabel.text = _firstNameString;
}

-(void)setFirstName:(NSString *)firstName
{
    _firstNameString = firstName;
}
@end

//SecondVC.h

#import <UIKit/UIKit.h>

@protocol passNames <NSObject>
-(void)setFirstName:(NSString*)firstName;
@end

@interface SecondVC : UIViewController

@property (retain)id <passNames> delegate;

- (IBAction)send:(UIBarButtonItem *)sender;

@property (nonatomic, strong) NSString *firstNameString;
@property (weak, nonatomic) IBOutlet UITextField *firstNameText;
@end

//SecondVC.m

#import "SecondVC.h"
#import "FirstVC.h"

@interface SecondVC ()

@end

@implementation SecondVC

- (IBAction)send:(UIBarButtonItem *)sender
{
    _firstNameString = _firstNameText.text;
    [[self delegate]setFirstName:_firstNameString];
    [self dismissViewControllerAnimated:YES completion:nil];
}
@end

谁能解释一下prepareForSegue方法在上面的代码中是如何工作的?这个问题的原因是因为我添加了一个 NSLog 并且看起来这个方法只在从主视图控制器到第二个控制器的转换中被调用。如果在从第二个视图控制器转换到主视图控制器时不调用此方法,为什么需要此方法,在我的情况下,这就是我正在做的事情?在将数据从主视图控制器传递到第二个控制器时使用它是有意义的,而不是上面显示的情况。

可以解释一下将数据传回主视图控制器时的整个机制吗?

仅供参考,我确实了解协议和授权。

非常感谢。

【问题讨论】:

    标签: ios objective-c uiviewcontroller delegation


    【解决方案1】:

    在您的情况下,您在prepareForSegue 中的mainViewController 中将第二个视图控制器的委托方法设置为self。这意味着除了导航到 SecondViewController 之外,您还在主视图控制器中实现回调机制,以便在从第二个视图控制器传递值时调用您的委托方法,并且此委托方法将值作为参数收集到在主视图控制器中处理它。您可能已将 VC2 的委托设置为您的 prepareForSegue 的 self inn,因为您正在此方法中创建 VC2 的实例以导航到第二个控制器。

    【讨论】:

      【解决方案2】:

      您的目标是交回数据,如下所示:

      [[self delegate] setFirstName:_firstNameString];
      

      但你不能这样做,除非你知道setFirstName:发送给,并且编译器不会你这样做,除非你保证谁您正在发送 setFirstName: 以接受该消息。

      这就是prepareForSegue 准备的。 FirstVC 已经声明它采用passNames 协议,这意味着它实现了setFirstName:。现在你在说:

      [vc2 setDelegate:self];
      

      ...其中self FirstVC 实例。这同时解决了这两个问题。 SecondVC 实例 (vc2) 现在有一个委托 (FirstVC 实例),它是将信息发送回的正确对象,并且因为它的委托被声明为采用 passNames,我们知道 SecondVC 实际上可以向该委托发送setFirstName:

      现在回到您实际问题的核心:在prepareForSegue 中这样做的原因仅仅是这是 FirstVC 实例和 SecondVC 实例“相遇”彼此的唯一时刻!没有其他时刻 FirstVC 实例具有对 SecondVC 实例的引用,以便能够首先在其上调用setDelegate。如果您不使用 segue 和故事板,FirstVC 将直接创建 SecondVC 实例 - 并将自己设置为其委托,就像您所做的那样:

      SecondVC *vc2 = [SecondVC new];
      UINavigationController *nav = [
          [UINavigationController alloc] initWithRootViewController: vc2];
      [vc2 setDelegate:self];
      [self presentViewController: nav animated: YES completion: nil];
      

      这是我不喜欢故事板的原因之一:它们使故事变得混乱。当您使用它们而只是像这样直接做所有事情时,一切都那么简单明了。

      【讨论】:

      • 看我书中的讨论:apeth.com/iOSBook/ch10.html#_protocols
      • 我实际上拥有您的《iOS 5 编程》一书。非常好的书!非常感谢。
      • 在新版本(iOS 7 版本)中对这一点(以及许多其他问题)的解释,很抱歉,是一个更好的解释......!
      • 酷,iOS 7 Programming Fundamentals 和 Programming iOS 7 有什么区别?
      • 第一个真的很基础吗?
      猜你喜欢
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-22
      • 2013-01-08
      • 2018-05-01
      • 1970-01-01
      相关资源
      最近更新 更多