Использование настраиваемого подкласса объекта NS в двух различных IBActions

Это проблема объективного c. Я создал подкласс NSObject с параметрами «высота» и «вес», со свойством и синтезом в файле с именем Person.h, который содержит как интерфейс, так и реализацию.

Я хочу импортировать Person.h в свой viewcontroller.m и создавать объекты person и изменять их с помощью 2 IBActions.

-(IBAction)alterperson_1{

 person *bob = [person alloc]init];
 bob.height = 72;
 bob.weight = 200;
}

-(IBAction)alterperson_2{

 bob.height = 80;
 bob.weight = 250;

}

Этот механизм не работает, потому что метод alterperson_2 не может найти Боба, потому что это локальная переменная для alterperson_1. Мой вопрос в том, как и где в viewcontroller.m мне выделить Боба как человека, чтобы его атрибуты могли быть изменены обоими IBActions.

Я пробовал размещать в viewdidload, а также в методах initwith nibname. Это не работает. Я также пробовал реализовать {} viewcontroller.m, но это тоже не сработало, потому что распределение Боба не является постоянной времени компиляции.

Спасибо!

Обновить с помощью кода

Итак, теперь у меня есть файл Person.h, импортируемый правильно (спасибо Robotnik), и я могу создавать экземпляры Person во всем ViewController.m - однако мой созданный экземпляр * bob, похоже, не сохраняет значения для своих свойств (см. Комментарии с помощью операторов NSLog в коде). Я думаю, что это проблема инициализации, но я не знаю, где инициализировать. В настоящее время я получаю предупреждение при инициализации в viewDidLoad. Как мне заставить bob.weight печатать 200 при вызове моего IBAction вместо 0, которое я получаю сейчас? Спасибо.

// Person.h

#import <Foundation/Foundation.h>

@interface Person : NSObject{

int weight;
int height;
}

@property int weight, height;

@end

конец Person.h

//Person.m


#import "Person.h"

@implementation Person

@synthesize weight, height;

@end

конец Person.m

//ViewController.h

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



@interface ViewController : UIViewController{


}

@property Person *bob;

-(IBAction)persontest:(id)sender;

@end

конец ViewController.h

//ViewController.m

#import "ViewController.h"

@implementation ViewController

@synthesize bob;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    Person *bob = [[Person alloc]init]; // this causes a local declaration warning, if I remove this code, however, it still doesn't work
    bob.weight = 100;
    NSLog(@"viewDidLoad bob's weight, %i", bob.weight); // this will print 100, but only because I made the local initialization. The value is lost once the viewDidLoad Method ends.
}

-(IBAction)persontest:(id)sender{

    bob.weight = bob.weight + 100;
    NSLog(@"IBAction bob's weight %i", bob.weight); // this prints 0, probably because value is nil. How can I make it print 200?
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

@end

конец ViewController.m


person CaptainBear    schedule 06.06.2012    source источник
comment
Не относится к вопросу, но не забывайте, что имена классов должны быть написаны с заглавной буквы, чтобы отличать их от имен объектов. Кроме того, вам не хватает [из строки выделения человека (я предполагаю, что это просто опечатка в вопросе, а не в вашем фактическом коде).   -  person    schedule 06.06.2012
comment
Вы правы, это опечатка. И я предполагаю, что использование заглавных букв в именах классов является условностью, поэтому я обновлю свою программу, чтобы следовать ей. Спасибо, Адам!   -  person CaptainBear    schedule 06.06.2012


Ответы (2)


Вам нужно будет объявить Боба в вашем ViewController.h, если вы хотите, чтобы он был доступен несколькими методами. Затем вы можете инициализировать его в viewDidLoad

@interface ViewController
{
    Person *bob;
}

-(IBAction)alterperson_1;
-(IBAction)alterperson_2;
@end

Вы упомянули, что хотите создать несколько человек. В этом случае вы можете захотеть сохранить несколько объектов Person в NSMutableArray или подобном. Это все еще должно быть объявлено в ViewController.h, чтобы оно было доступно несколькими методами. Затем вы можете использовать метод addObject: для добавления людей в массив. Вот пример массива, хранящего строки.

NSMutableArray *stringArray = [[NSMutableArray alloc] init];

[stringArray addObject:@"Dog"];
[stringArray addObject:@"Cat"];
person Robotnik    schedule 06.06.2012
comment
Спасибо за ваш быстрый ответ. Я несколько раз пытался выделить person * bob в viewDidLoad, но тогда * bob по-прежнему недоступен в моих IBActions. Я использую ARC, может в этом проблема? Мои объекты выпускаются слишком рано? - person CaptainBear; 06.06.2012
comment
Но вы объявили его в файле .h, как предложил Роботник? Этот подход (объявления * bob) будет работать только в том случае, если вы знаете все имена объектов Person, которые собираетесь использовать, поскольку вам нужно объявить свойство или ivar для каждого из них. Добавление их в коллекцию сохранит их (если будет сохранен массив или набор), так что, вероятно, вы хотите пойти именно так. - person rdelmar; 06.06.2012
comment
Ладно, я собираюсь это сделать здесь. Если я импортирую person.h в viewcontroller.h, я получаю ошибку при сборке команды компоновщика. Я предполагаю, что это связано с тем, что person.h импортируется в viewcontroller.h, а затем снова импортируется в viewcontroller.m, что создает несколько копий person.h. Вот почему я пытался разобраться только с файлом .m. - person CaptainBear; 06.06.2012
comment
но если Person.h находится в ViewController.h, он вам не нужен в ViewController.m-, потому что, когда ViewController.m включает ViewController.h, он также увидит Person.h - person Robotnik; 06.06.2012
comment
Я использую XCode 4.3 с ARC. Я импортирую Person.h только в ViewController.h - думаю, моя проблема в том, что мне нужно разделить Person.h на Person.h и Person.m. Я сделаю это сегодня вечером и попробую, когда вернусь домой с работы. Спасибо за помощь Роботнику, надеюсь, это сработает. - person CaptainBear; 06.06.2012
comment
Хорошо, объявление Person * bob в ViewController.h действительно позволяет мне инициализировать bob в ViewDidLoad и изменять bob в любых IBActions. Однако теперь у меня возникла новая проблема. - person CaptainBear; 07.06.2012
comment
Хорошо, объявление Person * bob в ViewController.h действительно позволяет мне инициализировать bob в ViewDidLoad и вызывать bob в любых IBActions. Однако теперь у меня возникла новая проблема. Я кодирую bob.weight = 200 в IBAction, и я кодирую NSLog (это вес,% i, bob.weight) в том же самом IBAction. Теперь я запускаю симулятор и нажимаю соответствующую кнопку, я получаю в выводе «это вес, 0, а не 200». В принципе, кажется, что инициализация переменной не переживает ViewDidLoad. Это ARC? - person CaptainBear; 07.06.2012
comment
Я не уверен, извините, вы можете отредактировать свой вопрос с помощью обновленного кода? (или задайте новый вопрос) - person Robotnik; 07.06.2012
comment
Согласно приведенному ниже jrturton, последней частью ниже было удаление символа '*' при инициализации bob в viewDidLoad, поэтому ваше первоначальное решение действительно работает. Спасибо за уделенное время, Роботник. - person CaptainBear; 07.06.2012
comment
Не беспокойтесь, мы рады помочь :) - person Robotnik; 08.06.2012

Кажется, вы путаете объявление переменной с выделением переменной. Вы также неправильно используете свойства.

Объявление переменной делается так:

Person *bob;

Вот и все. Если вы поместите эту строку в свой раздел @interface или в {фигурные скобки} в верхней части раздела реализации, тогда она станет переменной экземпляра, каждый раз, когда вы используете bob в остальной части вашего класса, она будет знать, что вы разговариваете с человеком. Итак, в вашем viewDidLoad теперь вы можете сделать это:

bob = [[Person alloc] init];

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

Глядя на природу этого вопроса и на ваши комментарии, я настоятельно рекомендую прочитать несколько вводных текстов, прежде чем двигаться дальше. Здесь вы можете задавать вопросы, но SO на самом деле не место для изучения языка - большинство респондентов предполагают, что вы знаете основы языка.

person jrturton    schedule 07.06.2012
comment
Я застрял на этом 2 дня. Хотя у меня есть опыт работы с C ++, SQL, SAS, Visual Basic, Objective C для меня совершенно новый. Я сделал все учебники The New Boston по Objective C, которые были действительно полезны, но да, я делал довольно много ошибок новичков. Эта конкретная проблема сводила меня с ума, поэтому я спросил ТАК. Спасибо за вашу помощь, и в эти выходные я уделю немного больше времени обучающим материалам. - person CaptainBear; 07.06.2012