我正在尝试一些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报告调用方法,但标签不会更改。这有什么不对?
(请注意:可能会出现一些小错误,因为我不得不输入其中的一些内容,因为我目前没有提供所有代码)。
答案 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()
运行但标签未更新,则几乎可以肯定lbl1
和lbl2
为零。它们几乎肯定是零,因为它们实际上并未在IB中连接,或者您在-viewDidLoad
运行之前运行此代码。在您的设计中,您必须避免-updateLabels
,直到视图实际加载并连接其插座。视图延迟加载,因此在第一次显示视图之前不会创建这些标签。
简短版本是您应该在-updateLabels
中调用-viewDidLoad
。
答案 2 :(得分:0)
好的,这段代码的几个方面令人困惑,所以我将从对象和类之间的明显区别开始。
目的是什么:
NSObject *UpdateClassObject;
这是什么?如何分配(从笔尖?)?从名称来看,您似乎只需要一个UpdateClass类的实例,其目的是:
UpdateClass *updateClass;
你似乎没有使用前者,所以我不确定为什么它会在那里。
现在,问题的关键在于:您正在调用[updateClass updateLabels]
并且您的NSLog语句表明它确实被调用了。这告诉我,最可能的问题是标签lbl1
和lbl2
的实例实际上都是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。另请考虑使用基类。