【问题标题】:Passing data between ViewController and TabBar children在 ViewController 和 TabBar 子项之间传递数据
【发布时间】:2013-10-01 01:10:51
【问题描述】:

我正在开发一个具有 TableView 的应用程序。当我按下任何单元格时,应用程序会转到下一个 ViewController。在这个 viewController 中,我通过代码创建了一个 TabBarController,它有 3 个子 ViewControllers。因此,我想将 TableView 中的变量传递给 TabBar 的子项。我可以将变量传递给 TabBar,我已经用 NSlog 函数观察了它。对我来说真的很奇怪,在子 ViewControllers 中我还输入了一个 NSlog 并且变量为 null,但在输出中我首先看到了这个。

2013-10-01 03:01:40.687 Prototype[38131:c07] proId (null) // This is the children log from vc2 ViewController  "YPProjectViewController"
2013-10-01 03:01:40.697 Prototype[38131:c07] projectID 433 // This is the TabBar LOG YPTabBarViewController 

有人知道为什么我可以先查看 Children NSLog 吗?也许有解决办法。

#import "YPTabBarViewController.h"
#import "YPProjectViewController.h"
#import "YPCommentsViewController.h"
#import "YPProposalsViewController.h"

@interface YPTabBarViewController ()
@property (nonatomic,strong)UITabBarController *tabBar;
@end

@implementation YPTabBarViewController
@synthesize tabBar;
@synthesize projectId = _projectId;

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setUpTabBar];

}

// Set up tabBar
-(void)setUpTabBar
{

        YPCommentsViewController *vc1 = [[YPCommentsViewController alloc] init];
        vc1.title = @"Comments";
        vc1.view.backgroundColor = [UIColor clearColor];
        UINavigationController *contentNavigationController = [[UINavigationController alloc] initWithRootViewController:vc1];

        YPProjectViewController *vc2 = [[YPProjectViewController alloc] init];
        vc2.title = @"Project";
        vc2.view.backgroundColor = [UIColor clearColor];

        vc2.proId = _projectId;
        NSLog(@"PROJECT ID %@", vc2.proId);
       // UINavigationController *contentNavigationController2 = [[UINavigationController alloc] initWithRootViewController:vc2];


        YPProposalsViewController *vc3 = [[YPProposalsViewController alloc] init];
        vc3.title = @"Proposal";
        vc3.view.backgroundColor = [UIColor clearColor];
        UINavigationController *contentNavigationController3 = [[UINavigationController alloc] initWithRootViewController:vc3];
        tabBar = [[UITabBarController alloc] init];
        tabBar.viewControllers = @[contentNavigationController,vc2,contentNavigationController3];
        tabBar.selectedIndex   = 1;

        [tabBar.view setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
        [tabBar willMoveToParentViewController:self];
        [self addChildViewController:tabBar];
        [tabBar didMoveToParentViewController:self];
        [self.view addSubview:tabBar.view];

}

【问题讨论】:

  • 对不起,我已经编辑了这个问题。你说的是真的
  • 你是这个意思吗? @implementation YPProjectViewController -(id) init { self = [super init]; if( !self ) return nil; NSLog(@"proId ID %@", _proId); return self; }
  • 但是,我不是在 init 中看的,我已经这样做给你看,我在 ViewDidLoad 中显示 proId 日志

标签: iphone ios objective-c uitableview uitabbarcontroller


【解决方案1】:

就理解问题而言,您在“标签栏控制器”中的NSLog 语句在设置后立即记录vc2.proID 的值。但是您的 NSLog 输出向我们显示,第二个选项卡的视图控制器正在记录其结果之前。这就是为什么当第二个标签的视图控制器的 viewDidLoad 记录它时它是 nil 的原因,因为该日志是在标签栏控制器有机会设置值并自行记录之前发生的。

所以,有几种方法可以解决这个问题:

  1. 就在您分配vc2.proId 之前,您有一行无害的代码:

    vc2.view.backgroundColor = [UIColor clearColor];
    

    那行代码触发了第二个视图控制器的视图被加载(并且它的viewDidLoad 将被调用)。如果您在开始访问vc2 的任何视图之前将vc2.proId 的分配移动到,这将改变您的NSLog 语句出现的顺序(或者,更好的是,将背景颜色的设置移动到@ 987654332@ 的子控制器)。

  2. 您可以创建自己的init 方法,接受项目ID 作为参数。这也将确保它设置在viewDidLoad 之前。因此,YPProjectViewController 可以有如下方法:

    - (id)initWithProjectId:(NSString *)projectId
    {
        self = [self init];
    
        if (self)
        {
            _proId = projectId;
        }
    
        return self;
    }
    

关于自定义容器调用的两个不相关的观察结果:

  1. 当您调用addChildViewController 时,它会为您调用willMoveToParentViewController。所以你应该删除对willMoveToParentViewController 的调用。请参阅documentation for that method

  2. 您甚至可能希望完全停用这些自定义容器调用,只需将 YPTabBarViewController 本身设为 UITabBarController 的子类,而不是 UIViewController。这完全消除了自定义容器调用的需要。显然,如果您对自定义容器有其他需求,请随意,但在此代码示例中它是多余的。

【讨论】:

  • 我想说的和这里的 Rob 差不多。我要补充一点,您在这里设置的大多数控制器属性,在我看来,应该由控制器自己处理。标题和背景颜色。 didmoves 和 willmoves 肯定不属于这里。我会推荐 Rob 的自定义启动器的想法,并且这些视图之间的任何其他通信都应该通过委托/协议或 NSNotification 酌情处理。
  • @DeanDavids 同意。顺便说一句,这不仅仅是一个好的风格问题,还有性能/内存原因不让这个标签栏控制器不尝试更新子控制器的view 对象。如果标签栏控制器访问每个子视图,它将预先加载所有这些视图。没有理由遭受这种(适度的)打击。如果您将这些视图更新推迟到各个子项的viewDidLoad,则在您绝对需要它们之前不会创建它们的视图(例如,用户点击该选项卡)。因此,启动更快并消耗更少的内存。
猜你喜欢
  • 1970-01-01
  • 2016-03-24
  • 2017-01-22
  • 1970-01-01
  • 1970-01-01
  • 2019-12-05
  • 1970-01-01
  • 2020-08-23
  • 1970-01-01
相关资源
最近更新 更多