2009-07-24 4 views
1

Я пытаюсь использовать некоторые возможности программирования на iPhone, и я сталкиваюсь с тем, что может быть довольно очевидным для ветеранов, но я не совсем уверен, почему это происходит. У меня есть два класса UIViewController, и я хочу получить доступ к методу из другого класса. У меня есть два класса NSObject, связанных с обоими из них в IB (с файлом Class как UpdateClass для каждого), и я пытаюсь создать класс и вызвать метод. Кажется довольно простым, но проблема в том, что он вызывает метод (согласно NSLog), но он не обновляет метки. Вот мой код:iPhone - Пользовательский класс не будет использовать метод

//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 
} 

Итак, есть NSObject, подключенный к IB для обоих видов. Существует метка на каждом представлении, подключенном к NSObject, и Владелец файла (возможно, нет необходимости подключать их к обоим). Когда кнопка нажата (которая также правильно подключена в IB), метка должна перейти к некоторой строке. NSLog сообщает, что методы вызываются, но метки не меняются. Что здесь не так?

(обратите внимание: могут быть некоторые небольшие ошибки, поскольку я должен был напечатать некоторые из них, потому что у меня нет всего кода со мной в данный момент).

+0

им интересно, почему вы используете класс только для хранения этикеток и обновить их? Также интересно, добавляете ли вы метки в этих классах в представление UIViewControllers – Daniel

+0

Ну, потому что я решил, что какой-то централизованный класс для обработки обновлений имеет смысл ... Но, возможно, я не понимаю, как программирование Objective-C должно Работа. – 2009-07-24 17:25:13

+0

Нет необходимости в этом, вы можете просто обработать обновление ярлыков в вашем UIViewCOntroller напрямую, вот что такое контроллеры для управления вашими взглядами. – Daniel

ответ

0

Если NSLog() работает, но этикетки не обновляются, это почти наверняка, что lbl1 и lbl2 - это нуль. Они почти наверняка ноль, потому что они фактически не подключены в IB, или вы используете этот код до запуска -viewDidLoad. В вашем дизайне здесь вы должны избегать -updateLabels до тех пор, пока изображение не загрузится и не подключится к его выходам. Представления загружаются лениво, поэтому эти метки не будут создаваться до тех пор, пока не появится представление в первый раз.

Короткий вариант заключается в том, что вы, вероятно, должны звонить -updateLabels в -viewDidLoad.

+0

Как это можно обрабатывать, если значения меняются? Например, в реальной программе строка someWord может быть изменяющейся переменной. Это плохой способ настроить программу, которая часто меняет текст ярлыков? – 2009-07-24 17:29:01

+0

Если текст изменяется часто, то вам, вероятно, следует использовать уведомления, чтобы обновлять элементы пользовательского интерфейса. Должен быть объект Model, у которого есть данные, которые вы представляете. Когда данные изменяются, он должен опубликовать уведомление. ViewController, когда он виден (и только тогда, когда он виден), должен наблюдать это уведомление и обновлять метку в соответствии с новым значением. Вы должны использовать -viewWillAppear/Disappear для подписки и отмены подписки на уведомления. http://developer.apple.com/documentation/Cocoa/Концептуальные/Уведомления/http://robnapier.net/blog/thoughts-nsnotifications-42 –

0

ОК, есть несколько аспектов этого кода, которые сбивают с толку, поэтому я начну с очевидного различия, которое вы делаете между объектами и классами.

Какова цель:

NSObject *UpdateClassObject; 

Что это? Как это назначается (из ниба?)? Из названия, кажется, вы просто хотите экземпляр вашего класса UpdateClass, что цель:

UpdateClass *updateClass; 

Вы, кажется, не использовать прежний, так что я не знаю, почему он там вообще ,

Теперь, к сути вашей проблемы: вы вызываете [updateClass updateLabels], и ваш оператор NSLog указывает, что он действительно вызывается. Что говорит мне, что наиболее вероятной проблемой являются оба экземпляра ваших ярлыков lbl1 и lbl2 - это фактически nil. Помните, что в Objective-C отправка сообщения (например, updateText:) в nil не приведет к ошибкам, он просто сработает молча.

Так почему же они ноль? Ну, они объявлены как IBOutlet s, что заставляет меня думать, что у вас есть файл NIB, владельцем файла которого является UpdateClass, который выполняет фактическую проводку некоторых UILabel s вашим переменным-членам.Если это так, то вам необходимо initialze updateClass с СИБ правильно:

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

Но то, что вы на самом деле делаете:

updateClass = [[UpdateClass alloc] init]; 

Это означает, что класс никогда не инициализируется из СИБ и ваш этикетки никогда не подключаются.

Конечная точка, использующая слово «класс» в ваших именах классов, довольно избыточна - это, очевидно, класс. Это также может привести к путанице - переменная экземпляра, хранящая ваш экземпляр UpdateClass in, называется updateClass - для меня это означало бы ее фактическое сохранение экземпляра объекта, тип которого Class (который вы могли бы получить, позвонив по телефону [SomeClass class]).

0

Вы отправляете сообщение updateLabels в неправильный UpdateClass.

Вы сказали, что подключили экземпляр UpdateClass в InterfaceBuilder, который имеет соединения с метками, установленными в IB тоже. Таким образом, когда ваше представление загружено, у него есть объект UpdateClass, введенный уже из NIB.

В вашей реализации viewDidLoad вы создаете новый экземпляр UpdateClass. У этого экземпляра нет установленных меток (они равны нулю). Таким образом, как только вы отправляете метод updateLabels на этот объект, у этого объекта нет ярлыков для обновления.

Просто выкиньте объявление и выделение updateClass в viewDidLoad и отправьте сообщение updateLabels в UpdateClassObject. Подумайте о переименовании члена UpdateCLassObject в updateClass или даже лучше, переименуйте класс на что-то вроде updater. Также рассмотрите возможность использования базового класса.

1

Слово на дизайн здесь:

Вы, кажется, хотите поделиться функциональности между двумя или более реализаций контроллера представления. В этом случае вам может понадобиться создать общий базовый класс, который выводится из UIViewController и выводит ваши два представления из этого класса. BaseView объявит выходы для общих компонентов пользовательского интерфейса, которые вы можете подключить в IB.

@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; 

...

Смежные вопросы