iPhone - 自定义类将无法访问方法

时间:2009-07-24 17:12:37

标签: iphone class methods label

我正在尝试一些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 个答案:

答案 0 :(得分: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;

...

答案 1 :(得分:0)

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

简短版本是您应该在-updateLabels中调用-viewDidLoad

答案 2 :(得分:0)

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

目的是什么:

NSObject *UpdateClassObject;

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

UpdateClass *updateClass;

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

现在,问题的关键在于:您正在调用[updateClass updateLabels]并且您的NSLog语句表明它确实被调用了。这告诉我,最可能的问题是标签lbl1lbl2的实例实际上都是nil。请记住,在Objective-C中,向updateText:发送消息(如本案例中的nil)不会抛出任何错误,它将无声地失败。

那为什么他们没有?好吧,它们被声明为IBOutlet s,这使我认为你有一个文件所有者为UpdateClass的NIB文件,它将一些UILabel的实际连接到你的成员变量。如果这是正确的,那么您需要正确地使用NIB初始化updateClass

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

但你实际做的是:

updateClass = [[UpdateClass alloc] init];

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

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

答案 3 :(得分:0)

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

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

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

在viewDidLoad中抛出updateClass的声明和分配,并将updateLabels消息发送到UpdateClassObject。考虑将成员UpdateCLassObject重命名为updateClass甚至更好,将类重命名为updater。另请考虑使用基类。