1

我正在尝试一些 iPhone 编程,我遇到了一些对退伍军人来说可能相当明显的事情,但我不确定它为什么会发生。我有两个 UIViewController 类,我想从另一个类访问一个方法。我在 IB 中有两个 NSObject 类与它们相关联(每个类的文件作为 UpdateClass),我正在尝试创建一个类并调用一个方法。看起来很简单,但问题是它正在调用该方法(根据 NSLog),但它没有更新标签。这是我的代码:

//UpdateClass.h
#import <Foundation/Foundation.h>

@interface UpdateClass : NSObject {
    IBOutlet UILabel *lbl1;
    IBOutlet UILabel *lbl2;
}

@property (nonatomic, retain) IBOutlet UILabel *lbl1;
@property (nonatomic, retain) IBOutlet UILabel *lbl2;

- (void)updateLabels;

@end

//UpdateClass.m

#import "UpdateClass.h"

@implementation UpdateClass

@synthesize lbl1;
@synthesize lbl2;


- (void)updateLabels {
    NSString *someWord = @"Whatever"; // This could be anything
    NSLog(@"NSObject Update");
    [lbl1 setText:someWord];
    [lbl2 setText:someWord];
}


@end

//ViewController1.h
#import <UIKit/UIKit.h>
@class UpdateClass;
@interface ViewController1 : UIViewController {
IBOutlet UIButton *button1;
NSObject *UpdateClassObject;
UpdateClass *updateClass;
}
@property (nonatomic, retain) IBOutlet UIButton *button1;
@property (nonatomic, retain) NSObject *UpdateClassObject;
@property (nonatomic, retain) UpdateClass *updateClass;
- (void)updateLabels:(id)sender;
@end

//ViewController1.m
#import "ViewController1.h"
#import "UpdateClass.h"

@implementation ViewController1
@synthesize button1;
@synthesize UpdateClassObject;
@synthesize updateClass;

- (void)viewDidLoad {
    [super viewDidLoad];
    updateClass = [[UpdateClass alloc] init];
}

- (void)updateLabels:(id)sender; { //This is connected to TouchDown on button1
    NSLog(@"Calls UpdateLabels");
    [updateClass updateLabels]; //Calls the class method
}

//ViewController2.h
#import <UIKit/UIKit.h>
@class UpdateClass;
@interface ViewController2 : UIViewController {
IBOutlet UIButton *button2;
NSObject *UpdateClassObject;
UpdateClass *updateClass;
}
@property (nonatomic, retain) IBOutlet UIButton *button2;
- (void)updateLabels:(id)sender;
@end

//ViewController2.m
#import "ViewController2.h"
#import "UpdateClass.h"

@implementation ViewController2
@synthesize button2;
@synthesize UpdateClassObject;
@synthesize updateClass;

- (void)viewDidLoad {
    [super viewDidLoad];
    updateClass = [[UpdateClass alloc] init];
}

- (void)updateLabels:(id)sender; { //This is connected to TouchDown on button2
    NSLog(@"Calls UpdateLabels");
    [updateClass updateLabels]; //Calls the class method
}

因此,IB 中为两个视图都连接了一个 NSObject。每个视图上都有一个连接到 NSObject 和文件所有者的标签(可能不需要将它们连接到两者)。当按下按钮时(在 IB 中也正确连接),标签应该变成一些字符串。NSLog 报告方法被调用,但标签没有改变。这里有什么问题?

(注意:可能会有一些小错误,因为我现在没有所有的代码,所以我不得不输入其中的一些)。

4

4 回答 4

1

关于设计的一句话:

您似乎希望在两个或多个视图控制器实现之间共享某些功能。在这种情况下,您可能希望创建一个从 UIViewController 派生的通用基类,并从该类派生您的两个视图。BaseView 将声明您可以在 IB 中连接的常见 UI 组件的出口。

@interface BaseUIViewController : UIViewController {
    IBOutlet UILabel *lbl1;
    IBOutlet UILabel *lbl2;
}

@property (nonatomic, retain) IBOutlet UILabel *lbl1;
@property (nonatomic, retain) IBOutlet UILabel *lbl2;

- (void)updateLabels;

@end

...

@interface ViewController1 : BaseUIViewController {
    IBOutlet UIButton *button1;

...

于 2009-07-24T17:41:40.230 回答
0

如果NSLog()运行但标签没有更新,则几乎可以肯定是这样lbl1并且lbl2为零。它们几乎可以肯定为零,因为它们实际上并没有在 IB 中连接,或者您在运行之前正在运行此代码-viewDidLoad。在您的设计中,您必须避免-updateLabels在视图实际加载并连接其插座之前。视图会延迟加载,因此这些标签要到第一次显示视图之前才会创建。

简短的版本是您可能应该调用-updateLabels.-viewDidLoad

于 2009-07-24T17:24:33.887 回答
0

好的,这段代码有几个方面令人困惑,所以我将从您在对象和类之间做出的明显区别开始。

目的是什么:

NSObject *UpdateClassObject;

它是什么?它是如何分配的(从笔尖?)?从名称看来,您似乎只是想要一个 UpdateClass 类的实例,其目的是:

UpdateClass *updateClass;

您似乎没有使用前者,所以我不确定它为什么会在那里。

现在,解决问题的症结所在:您正在调用[updateClass updateLabels]并且您的 NSLog 语句表明它确实被调用了。这告诉我,最可能的问题是您的标签实例lbl1lbl2实际上都是nil。请记住,在 Objective-C 中,发送消息(如updateText:本例所示)nil不会引发任何错误,它只会默默地失败。

那么为什么他们是零呢?好吧,它们被声明为IBOutlets 这让我觉得你有一个 NIB 文件,它的文件所有者是UpdateClass它实际将一些UILabels 连接到你的成员变量。如果这是正确的,那么您需要updateClass使用 NIB 正确初始化:

updateClass = [[UpdateClass alloc] initWithNibName:@"UpdateClass" bundle:nil]; // or whatever the nib is called

但你实际上在做的是:

updateClass = [[UpdateClass alloc] init];

这意味着该类永远不会从 NIB 初始化,并且您的标签永远不会被连接起来。

最后一点,在你的类名中使用“类”这个词是相当多余的——它显然是一个类。这也可能导致混淆——你存储 in 实例的实例变量UpdateClass被调用updateClass——对我来说,这意味着它实际上存储了一个类型为的对象的实例Class(你可以通过调用来获得[SomeClass class])。

于 2009-07-24T17:26:43.553 回答
0

您将 updateLabels 消息发送到错误的 UpdateClass。

你说你在 InterfaceBuilder 中连接了一个 UpdateClass 的实例,它也与 IB 中设置的标签有连接。因此,当您的视图被加载时,它已经从 NIB 注入了 UpdateClass 对象。

在您的 viewDidLoad 实现中,您创建了一个新的 UpdateClass 实例。该实例没有设置标签(它们为零)。因此,一旦您将 updateLabels 方法发送到该对象,该对象就没有要更新的标签。

只需将viewDidLoad中updateClass的声明和分配丢掉,将updateLabels消息发送给UpdateClassObject即可。考虑将成员 UpdateCLassObject 重命名为 updateClass,或者更好的是,将类重命名为 updater 之类的名称。还可以考虑改用基类。

于 2009-07-24T17:35:24.363 回答