iPhone - 自定義類將無法訪問方法

[英]iPhone - Custom Class Won't Access Method


I'm trying my hand at some iPhone programming and I've run across something that may be fairly obvious to veterans but I'm not exactly sure why it's happening. I have two UIViewController classes, and I want to access a method from the other class. I have two NSObject classes associated with both of them in IB (with the Class file as UpdateClass for each), and I'm trying to create a class and call a method. Seems pretty easy, but the problem is that it's calling the method (according to NSLog) but it's not updating the labels. Here's my code:

我正在嘗試一些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
}

So there is an NSObject hooked up in IB for both Views. There is a label on each view hooked up to the NSObject and the File's Owner (may not be necessary to hook them up to both). When the button is pressed (which is also hooked up properly in IB), the label is supposed to change to some string. NSLog reports that the methods are called, but the labels don't change. What's wrong here?

因此,對於兩個視圖,在IB中都連接了一個NSObject。每個視圖上都有一個標簽,連接到NSObject和文件所有者(可能沒有必要將它們連接到兩者)。按下按鈕(也在IB中正確連接)時,標簽應該更改為某個字符串。 NSLog報告調用方法,但標簽不會更改。這有什么不對?

(note: there may be some small mistakes as I had to type out some of this because I don't have all the code with me at the moment).

(注意:可能會有一些小錯誤,因為我必須輸入其中一些,因為我目前沒有所有代碼)。

4 个解决方案

#1


A word on design here:

關於設計的一句話:

You seem to want to share some functionality among two or more view controller implementations. In this case, you may want to create a common base class that derives from UIViewController and derive your two views from that class. The BaseView would declare the outlets for common UI components which you can connect in IB.

您似乎想要在兩個或多個視圖控制器實現之間共享某些功能。在這種情況下,您可能希望創建一個從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;

...

#2


If the NSLog() runs but the labels don't update, it's almost certainly that lbl1 and lbl2 are nil. They are almost certainly nil because they're not actually connected in IB, or you're running this code prior to -viewDidLoad running. In your design here, you must avoid -updateLabels until after the view has actually loaded and wired its outlets. Views load lazily, so these labels won't be created until right before displaying the view for the first time.

如果NSLog()運行但標簽沒有更新,那么幾乎可以肯定lbl1和lbl2是nil。它們幾乎肯定是零,因為它們實際上並未在IB中連接,或者您在運行-viewDidLoad之前運行此代碼。在您的設計中,您必須避免-updateLabels,直到視圖實際加載並連接其出口。視圖延遲加載,因此直到第一次顯示視圖之前才會創建這些標簽。

The short version is that you should probably be calling -updateLabels in -viewDidLoad.

簡短的版本是你應該在-viewDidLoad中調用-updateLabels。

#3


OK, there's several aspects of this code that are confusing, so I'll start with the apparent distinction you are making between objects and classes.

好的,這段代碼的幾個方面令人困惑,所以我將從對象和類之間的明顯區別開始。

What is the purpose of:

目的是什么:

NSObject *UpdateClassObject;

What is it? How is it assigned (from a nib?)? From the name, it seems you simply want an instance of your UpdateClass class, which is the purpose of:

它是什么?如何分配(從筆尖?)?從名稱來看,您似乎只想要一個UpdateClass類的實例,其目的是:

UpdateClass *updateClass;

You don't appear to be using the former so I'm not sure why it's there at all.

你似乎沒有使用前者,所以我不確定它為什么會存在。

Now, on to the crux of your problem: You are calling [updateClass updateLabels] and your NSLog statement indicates that it is indeed being called. Which tells me that the most likely problem is both instances of your labels lbl1 and lbl2 are in fact nil. Remember, in Objective-C, sending a message (like updateText: in this case) to nil won't throw any errors, it will just fail silently.

現在,問題的關鍵在於:您正在調用[updateClass updateLabels]並且您的NSLog語句表明它確實被調用了。這告訴我最可能的問題是你的標簽實例lbl1和lbl2實際上都是零。請記住,在Objective-C中,將消息(例如updateText:在本例中)發送到nil不會拋出任何錯誤,它將無聲地失敗。

So why are they nil? Well, they are declared as IBOutlets which makes me think you have a NIB file whose file owner is UpdateClass which does the actual wiring of some UILabels to your member variables. If this is correct, then you need to initialze updateClass with the NIB correctly:

那為什么他們沒有?好吧,它們被聲明為IBOutlets,這讓我覺得你有一個NIB文件,其文件所有者是UpdateClass,它將一些UILabel的實際連接到你的成員變量。如果這是正確的,那么您需要正確地使用NIB初始化updateClass:

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

But what you are actually doing is:

但你實際做的是:

updateClass = [[UpdateClass alloc] init];

This means the class is never initialized from a NIB and your labels aren't ever being wired up.

這意味着該類永遠不會從NIB初始化,並且您的標簽不會被連接起來。

One final point, using the word 'Class' in your class names is fairly redundant - its obviously a class. This can also lead to confusion - the instance variable you are storing your instance of UpdateClass in is called updateClass - to me, this would mean its actually storing an instance of an object whose type is Class (which you could get by calling [SomeClass class]).

最后一點,在類名中使用“類”這個詞是相當多余的 - 它顯然是一個類。這也可能導致混淆 - 你正在存儲你的UpdateClass實例的實例變量叫做updateClass - 對我來說,這意味着它實際上存儲了一個類型為Class的對象的實例(你可以通過調用[SomeClass類來獲得] ])。

#4


You are sending the updateLabels message to the wrong UpdateClass.

您正在將updateLabels消息發送到錯誤的UpdateClass。

You said you hooked up an instance of UpdateClass in InterfaceBuilder which has the connections to the labels set in IB too. Thus, when your view is loaded, it has the UpdateClass object injected already from the NIB.

你說你在InterfaceBuilder中連接了一個UpdateClass實例,它也與IB中設置的標簽有關。因此,在加載視圖時,它已經從NIB注入了UpdateClass對象。

In your viewDidLoad implementation you create a new instance of UpdateClass. That instance does not have the labels set (they are nil). Thus, once you send the updateLabels method to that object, that object has no labels to update.

在viewDidLoad實現中,您將創建UpdateClass的新實例。該實例沒有設置標簽(它們是零)。因此,一旦將updateLabels方法發送到該對象,該對象就沒有要更新的標簽。

Just throw out the declaration and allocation of updateClass in viewDidLoad and send the updateLabels message to UpdateClassObject. Consider renaming the member UpdateCLassObject to updateClass or even better, rename the class to something like updater. Also consider using a base class instead.

只需在viewDidLoad中拋出updateClass的聲明和分配,並將updateLabels消息發送到UpdateClassObject。考慮將成員UpdateCLassObject重命名為updateClass甚至更好,將類重命名為updater。另請考慮使用基類。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2009/07/24/8b1e78298fee44b49e13427f801f5abe.html



 
  © 2014-2022 ITdaan.com 联系我们: