在基于导航的iOS应用程序中以编程方式从App Controller更改UILabel

时间:2010-11-07 01:00:48

标签: objective-c cocoa-touch ios

我在看起来很简单的事情上遇到了很多麻烦。我无法以编程方式从基于导航的iOS应用程序更新UILabel。我不想使用按钮,因为此标签旨在报告外部系统的状态,并应在启动时更新。如果我不需要,则无需让用户通过触摸按钮的额外步骤。

以下是我采取的步骤的详尽列表。如果其中一些似乎没有必要,我很抱歉,但根据我的经验,即使是最小的遗忘步骤也可能是问题的原因。

来自Xcode中一个全新的基于导航的应用程序,这里是我正在采取的步骤:

  1. 将UITableView替换为通用UIView类
  2. 将文件所有者的视图插座重新连接到新的UIView
  3. 将UILabel添加到UIView的中心,使文本居中,并保留默认文本。
  4. 保存并退出Interface Builder
  5. RootViewController.h
    #import <UIKit>
    @interface RootViewController : UIViewController {
        UILabel *myLabel;
    }
    @property (nonatomic, retain) IBOutlet UILabel *myLabel;
    @end
  6. RootViewController.m <UIKit>
  7. 从RootViewController.m
  8. 中删除了TableView内容
  9. 将IBOutlet myLabel连接到RootViewController.xib中的标签
  10. 保存并退出Interface Builder
  11. tempNavAppAppDelegate.m
    #import "RootViewController.h"
    @implementation RootViewController
    @synthesize myLabel;
    ...
  12. 构建/运行
  13. 标签显示为“标签”而不是“测试”。日志报告:

    ...
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
    // Add the navigation controller's view to the window and display. [self.window addSubview:navigationController.view]; [self.window makeKeyAndVisible];
    RootViewController *rootViewCont = navigationController.visibleViewController; rootViewCont.myLabel.text = @"test"; NSLog(@"Label Text: %@", rootViewCont.myLabel.text);
    return YES; } ...

    我已经尝试了许多不同的方法来完成这项工作,但任何帮助都会受到赞赏。

4 个答案:

答案 0 :(得分:2)

旅程

在发现我的rootViewCont.myLabel也是零之后,感谢mprudhom的帮助,我决定测试并查看是否可以在RootViewController.m myLabel.text中分配- (void)viewDidLoad值1}}方法。 它工作,我能够直接从RootViewController更改文本。虽然这证明了我的View Controller没有被破坏,但它并没有解决我最初想要从tempNavAppAppDelegate.m更改UILabel的愿望。

Elliot H.然后建议navigationController.visibleViewController实际上没有返回视图控制器。我测试了rootViewCont的值,它作为RootViewController回来了,但是Elliot的建议让我想到了应用程序的生命周期以及我的代码的不同部分实际加载的时间。

所以我开始在启动过程的每一步打印一个NSLog(应用程序:didFinishLaunchingWithOptions:,applicationDidBecomeActive:,viewDidLoad,viewDidAppear :),我惊讶地发现[self.window makeKeyAndVisible];并不意味着视图将加载在申请之前:didFinishLaunchingWithOptions:已完成。

凭借掌握的知识,我知道问题出在哪里。解决方案(或至少我的解决方案)似乎是NSNotificationCenter。我现在在tempNavAppAppDelegate中注册了通知,我在RootViewController的viewDidAppear:方法中广播通知。


相关代码

RootViewController.h:

@interface RootViewController : UIViewController {
    IBOutlet UILabel *myLabel;
}
@property (nonatomic, retain) UILabel *myLabel;
@end

RootViewController.m:

@implementation RootViewController
@synthesize myLabel;
- (void)viewDidLoad {
    [super viewDidLoad];
    NSParameterAssert(self.myLabel);
}
- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"viewDidAppear" object:self];
}

tempNavAppAppDelegate.h:

@interface tempNavAppAppDelegate : NSObject  {
    UIWindow *window;
    UINavigationController *navigationController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
- (void)viewDidAppearNotification:(id)notification;
@end

tempNavAppAppDelegate.m:

@implementation tempNavAppAppDelegate
@synthesize window;
@synthesize navigationController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self.window addSubview:navigationController.view];
    [self.window makeKeyAndVisible];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(viewDidAppearNotification:) name:@"viewDidAppear" object:nil];
    return YES;
}
- (void)viewDidAppearNotification:(id)notification
{
    NSString *noteClass = [NSString stringWithFormat:@"%@", [[notification object] class]];
    if ([noteClass isEqualToString:@"RootViewController"]) {
        RootViewController *noteObject = [notification object];
        noteObject.myLabel.text = @"Success!";
    }
}

答案 1 :(得分:1)

如果此代码正在打印nil:

rootViewCont.myLabel.text = @"test";
NSLog(@"Label Text: %@", rootViewCont.myLabel.text);

然后几乎可以肯定,因为rootViewCont.myLabel本身是零。尝试记录rootViewCont.myLabel的值,你会看到。

您确定已将标签连接到Interface Builder中的UILabel IBOutput声明吗?这是最常见的问题。

我个人总是在viewDidLoad中声明我所有预期的出口,这样我就可以在Interface Builder中将出口(意外与否)分离出来时尽早发现。 E.g:

- (void)viewDidLoad {
    [super viewDidLoad];
    NSParameterAssert(rootViewCont.myLabel);
}

答案 2 :(得分:0)

你的界面应该是这样的

#import <UIKit>
@interface RootViewController : UIViewController {
    // IBOutlet here...
    IBOutlet UILabel *myLabel;
}
@property (nonatomic, retain) UILabel *myLabel;
@end

答案 3 :(得分:0)

visibleViewController实际上是否返回了视图控制器?我的猜测是因为application:didFinishLaunchingWithOptions:还没有返回,UINavigationController可能没有正确配置该属性返回,即使你已经将导航控制器的子视图添加到视图层次结构中,可能是visibleViewController不是有效直到viewDidAppear:在相关视图控制器上调用。

直接尝试将IBOutlet用于RootViewController,或以编程方式创建它,然后分配标签文本。

只是一般提醒:如果一个对象是nil(在这种情况下,visibleViewController将返回nil),并且你发送一条消息,你就不会崩溃,因为到nil的消息是有效的,不会做任何事情。当您在rootViewCont对象上调用myLabel访问器时,如果rootViewCont为nil,则myLabel将始终返回nil。