Objective-C: вызов экземпляра класса 2 из класса 1 [alloc init] не работает

У меня есть следующий метод в файле GameScreen.m с собственным объявлением - (void) drawNumbers в файле GameScreen.h:

//GameScreen.h
#import <UIKit/UIKit.h>

@interface GameScreen : UIView
{
  IBOutlet UIButton *cell00;
}
- (void) drawNumbers;
- (IBAction) onCellClick:(id)sender;
@property (nonatomic, retain) IBOutlet UIButton *cell00;

@end



//GameScreen.m

#import "GameScreen.h"
- (void) drawNumbers
{
   //testing if this works, so far it doesn't
   [cell00 setTitle:@"Whatever" forState:UIControlStateNormal];
   [cell00 setTitle:@"Whatever" forState:UIControlStateHighlighted];
}

Я пытаюсь вызвать этот метод из моего файла GameScreenViewController.m следующим образом:

//GameScreenViewController.m

#import "GameScreenViewController.h"
#import "GameScreen.h"
... 
- (void) viewDidLoad
{
   GameScreen *aGameScreen = [[GameScreen alloc] init];
   [aGameScreen drawNumbers];
   [aGameScreen release];

   [super viewDidLoad];
}

Предполагается, что это изменит заголовок кнопки в файле GameScreen.xib, где GameScreenViewController.m — это viewController, а класс GameScreen — обработчик событий, в котором я получаю все нажатия кнопок, запуск таймеров и т. д. Я пытаюсь вызвать [drawNumbers ] из [viewDidLoad], так как я хочу, чтобы заголовок менялся при выводе экрана на передний план (управление экраном осуществляется через файлы AppDelegate).

Дело в том, что если я вызову экземпляр drawNumbers внутри того же класса через

//GameScreen.m

#import GameScreen.h
-(void) onButtonClick:(id)sender
{
    //some other code

    [self drawNumbers];
}

он работает (как говорится, все в порядке с реализацией кода или графическим интерфейсом).

Я просмотрел Apple Guide и множество страниц в Интернете, но, похоже, не могу найти в этом никакой информации. Буду очень признателен за любую дополнительную помощь (включая ответы о том, где именно найти ответ в ADG).

(Отредактировано: здесь идет код AppDelegate для перехода к конкретному представлению, на всякий случай):

//myAppAppDelegate.h
#import <UIKit/UIKit.h>
@class myAppViewController, GameScreenViewController;
@interface myAppDelegate : NSObject <UIApplicationDelegate>
{
    UIWindow *window;
    myAppViewController *viewController;
    GameScreenViewController *gameScreenViewController;
}

- (void) flipToGameScreen;

@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) GameScreenViewController *gameScreenViewController;
@end

//myAppAppDelegate.m
-(void) flipToGameScreen
{
    GameScreenViewController *aGameScreenView = [[GameScreenViewController alloc] initWithNibName: @"GameScreen" bundle:nil];
    [self setGameScreenViewController:aGameScreenView];
    [aGameScreenView release];
    [gameScreenViewController.view.frame = [[UIScreen mainScreen] applicationFrame];
    [viewController.view removeFromSuperview];
    [self.window addSubview:[gameScreenViewController view]];
}

person Mario    schedule 28.10.2011    source источник
comment
Не могли бы вы опубликовать содержимое GameScreen.h?   -  person Suhail Patel    schedule 28.10.2011
comment
Как установлена ​​ваша переменная экземпляра cell00 в GameScreen? Это не показано здесь, и это может быть nil во время вызова метода -drawNumbers.   -  person    schedule 28.10.2011
comment
отредактировал как просили. вы также можете увидеть там переменную экземпляра ячейки.   -  person Mario    schedule 28.10.2011
comment
В вашем методе GameViewController.m viewDidLoad измените эту строку [выпуск GameScreen]; в [выпуск aGameScreen];   -  person denil    schedule 28.10.2011
comment
Опечатка здесь, мой плохой. объяснение отредактировано. Вам также понадобится файл AppDelegate?   -  person Mario    schedule 28.10.2011


Ответы (1)


Поскольку ваш cell00 должен быть установлен NIB, он будет равен нулю, если вы просто сделаете [[GameScreen alloc] init]. Он будет установлен только в том случае, если соответствующий NIB загружен (и соединение действительно установлено).

Если к ячейке можно получить доступ в вашем viewDidLoad, создайте свойство в GameScreen и передайте его через свойство (или выделенное initWithCell: или что-то в этом роде).

Если у вас есть что-то вроде IBOutlet GameScreen *aGameScreen; на вашем GameScreenViewController (а также установлено соединение с cell00 в том же NIB), вам следует получить к нему доступ.

person DarkDust    schedule 28.10.2011
comment
тогда я не понимаю; если все представления запускаются из AppDelegate с помощью определенного метода - (void) fliptoScreenX, и представление добавляется, не загружайте и viewController, и класс при отображении xib, поскольку viewController связан с владельцем файла и GameScreen с вид? - person Mario; 28.10.2011
comment
небольшой обходной путь: это сработало бы, если бы у меня были IBOutlets в классе ViewController и IBActions в классе GameScreen? У меня более 20 кнопок, это означает удвоить все переменные, что не очень хорошо... это нормально (с точки зрения «держать все в чистоте и простоте»)? - person Mario; 28.10.2011
comment
NIB/XIB десериализуется. Это означает, что все объекты в нем декодируются (через NSCoder), а ассоциации/соединения устанавливаются во время загрузки. Как только вы достигнете viewDidLoad, это будет сделано. Все созданные вами объекты не имеют никаких отношений с NIB/XIB. Если вы сделаете [[GameScreen alloc] init], ни один из ваших IBOutlet этого экземпляра не подключится. Обязательно прочтите все файлы Nib раздела Руководства по программированию ресурсов. - person DarkDust; 28.10.2011
comment
Спасибо за совет, я очень ценю это. Сделаю так, а пока я решил немного изменить свой код: AppDelegate будет работать как диспетчер представлений, ViewControllers будут действовать как выходные данные, а классы будут действовать как входные данные. Таким образом, я могу придерживаться модели MVC и при этом иметь чистый код... еще раз большое спасибо. - person Mario; 28.10.2011