Не удается получить объект-c для ответа на сообщение.Что мне не хватает? - PullRequest
0 голосов
/ 25 марта 2012

Я пытаюсь научить себя Objective-C и в качестве упражнения я пытаюсь написать приложение с одной кнопкой и одной меткой.Когда я нажимаю на кнопку, я хочу запустить расчет, а затем увидеть результаты в метке.Следующий код компилируется и запускается без ошибок или предупреждений, но, насколько я могу судить, вызов метода [object] ничего не делает.Я потратил на это часы и просто не понимаю, в чем дело.Кто-нибудь может объяснить проблему?Спасибо.

*** testMethodViewController.h ****

#import <UIKit/UIKit.h>
#import "testBrain.h"

@interface testMethodViewController : UIViewController 
{
    IBOutlet UILabel *display;
    testBrain *model;
}

- (IBAction)cellPressed:(UIButton *)sender;

@end

*** testMethodViewController.m ****

#import "testMethodViewController.h"

@implementation testMethodViewController

- (testBrain *)model 
{
    if (!model) {model = [[testBrain alloc] init];}
    return model;
}

- (IBAction)cellPressed:(UIButton *)sender
{
    int x = [model check:3];     //This method call doesn't work. But gets no errors.
    NSLog(@"Results from model: %i", x);  //Says x = 0, but I expect 6
    NSString *xAsString = [NSString stringWithFormat: @"testBrain: %i", x];
    display.text = xAsString;   //Label is updated and displays: testBrain: 0
}                               //I expect: testBrain: 6
@end

*** testBrain.h ****

#import <Foundation/Foundation.h>

@interface testBrain : NSObject {}

- (int) check:(int) anInteger;

@end

*** testBrain.m ****

#import "testBrain.h"

@implementation testBrain

- (int) check:(int) anInteger            //3 passed as the parameter.
{
    int r = anInteger + anInteger;
    NSLog(@"inside check %i", r);    //Debugging line: doesn't print.
    return r; 
}
@end

Ответы [ 5 ]

1 голос
/ 25 марта 2012

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

Это одна из причин, по которой вы часто видите переменные экземпляра в target-c, объявленные с начальным или конечным подчеркиванием. Если вы затем наберете model в любом месте вашего класса, это будет ошибка компилятора, заставляющая вас использовать метод доступа. Обычно это реализуется с помощью свойств и оператора синтеза:

В вашем интерфейсе:

@property (nonatomic, strong) TestBrain* model;

В вашей реализации:

@synthesize model = model_;

Ваш model метод будет:

-(TestBrain*)model
{
    if (!model_)
        model_ = [[TestBrain alloc] init];   
    return model_;
}

Затем вы будете использовать self.model вместо model в остальной части класса.

Если вы только начинаете, курс Stanford для iOS по iTunes U является отличным ресурсом, о многих материалах такого рода.

1 голос
/ 25 марта 2012

Когда этот код выполняется:

int x = [model check:3];

model - это nil. В Objective-C сообщения, отправленные на nil, ничего не делают и возвращают 0. Итак, как видите, x - это 0, а -check: никогда не вызывается.

Очевидно, вы ожидали, что этот метод будет вызван автоматически:

- (testBrain *)model 
{
    if (!model) {model = [[testBrain alloc] init];}
    return model;
}

Однако этот метод будет вызываться только в том случае, если вы сделаете это самостоятельно, сказав [self model] или self.model. Итак, эта строка исправит это:

int x = [[self model] check:3];

Попробуйте и посмотрите.

Пройдем немного дальше: было бы яснее полностью удалить метод model и создать переменную экземпляра model при создании UIViewController. Таким образом, мы можем гарантировать, что model действителен в любое время, когда выполняется любой код в классе testMethodViewController.

Это можно сделать, переопределив инициализатор UIViewController:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Now you can initialize your instance variables
        model = [[testBrain alloc] init];
    }

    return self;
}
0 голосов
/ 25 марта 2012

ты почти там. Вы должны использовать @property и @synthesize, чтобы завершить это. Директива @synthesize будет указывать компилятору создавать сеттеры и геттеры для определенного свойства. Директива @synthesize сообщает компилятору, что переменная является свойством. Свойства позволяют использовать точечный синтаксис. то есть self.model, который будет автоматически вызывать метод получения или установки, в зависимости от контекста.

В вашем файле testMethodViewController.h измените его следующим образом:

@interface testMethodViewController : UIViewController 
{
    IBOutlet UILabel *display;
    testBrain *model;
}
@property (nonatomic,retain) testBrain *model;

- (IBAction)cellPressed:(UIButton *)sender;

@end

тогда в реализации .m вам нужно использовать @synthesize после @implementation. Как это:

@implementation testMethodViewController
@synthesize model;  // tells the compiler to synthesize the setter and getter for you
- (testBrain *)model 
{
    if (!model) {model = [[testBrain alloc] init];}
    return model;
}

затем в вашем методе cellPressed: вам нужно использовать self.model для вызова метода получения:

- (IBAction)cellPressed:(UIButton *)sender
{
    int x = [self.model check:3];     //This method call doesn't work. But gets no errors.
    NSLog(@"Results from model: %i", x);  //Says x = 0, but I expect 6
    NSString *xAsString = [NSString stringWithFormat: @"testBrain: %i", x];
    display.text = xAsString;   //Label is updated and displays: testBrain: 0
}     

Надеюсь, это поможет.

0 голосов
/ 25 марта 2012
int x = [model check:3];

Эта строка должна быть:

int x = [self.model check:3];
0 голосов
/ 25 марта 2012

Я не вижу нигде в файле testMethodViewController.h

IBOutlet UIButton *button;

Также проверьте, правильно ли подключены все IBOutlet, IBAction и делегат, источник данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...