2012-11-06 4 views
1

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

Это мой ViewController.h:

@interface ViewController : UIViewController 
{ 
    @public 
    NSString *nameOfLabel; 
} 

@property (strong, nonatomic) IBOutlet UILabel *firstLabel; 
- (IBAction)Switch:(id)sender; 
- (IBAction)changeLabel:(UIButton *)sender; 
-(NSString *) nameOfLabel; 
@end 

nameOfLabel является публичной переменной и должен быть в состоянии получить доступ к внеклассной, верно?

ViewController.m:

#import "ViewController.h" 
#import "NewView.h" 

@interface ViewController() 
@end 

@implementation ViewController 

- (IBAction)Switch:(id)sender { 
    NewView * new = [[NewView alloc] initWithNibName:nil bundle:nil]; 
    [self presentViewController: new animated:YES completion:NULL]; 
} 
- (IBAction)changeLabel:(UIButton *)sender { 
    nameOfLabel = @"Test Name"; 
    _firstLabel.text = nameOfLabel; 
} 
-(NSString *) nameOfLabel { 
    return nameOfLabel; 
} 
@end 

changeLabel кнопка меняет * firstLabel.text на "имя Test".

второй класс NewView.h:

#import "ViewController.h" 

    @interface NewView : UIViewController 
    @property (strong, nonatomic) IBOutlet UILabel *secondLabel; 
    - (IBAction)changeSecondLabel:(UIButton *)sender; 
    @end 

и NewView.m:

#import "NewView.h" 

@interface NewView() 
@end 

@implementation NewView 
{ 
    ViewController *view; 
} 
- (IBAction)changeSecondLabel:(UIButton *)sender { 
    view = [[ViewController alloc] init]; 
    _secondLabel.text = view.nameOfLabel; 
} 
@end 

changeSecondLabel должны изменить secondLabel.text к nameOfLabel, который является 'название Test', однако, этикетка на самом деле исчезает, что заставляет меня думать, что имяOfLabel не может быть достигнуто. Ive играл с именемOfLabel, создавая его @property, а затем синтезируя его, а также пытающийся помещать его в {NSString * nameOfLabel; } в @implementation, но я все равно получаю тот же результат.

ответ

0

Эта строка: view = [[ViewController alloc] init]; создает новый ViewController, который ничего не знает о том, что вы, возможно, сделали с другим ViewController. В вашем случае он специально не знает, что changeLabel: был вызван на другой ViewController до того, как этот новый был когда-либо существовал.

+0

Хорошо, я удалил эту строку и все еще не работает. Даже если бы я должен был перейти к следующему виду и не изменитьLabel на первом представлении, метка все равно исчезнет. – PappaSmalls

+0

Это, безусловно, не сработает, если вы не сделаете «view» точкой для действительного объекта (то есть того, который имеет нужный ярлык). Если все, что вы делали, это удалить одну строку, вы перешли от использования нового объекта к тому, чтобы вообще ничего не использовать. –

+0

Как я могу сделать точку зрения на метку первого ViewController? – PappaSmalls

0

Прежде всего, пожалуйста, прочитайте о стандартах кодирования, это не очень хорошая практика:

  1. имя переменных, как "новые"

  2. методы Имя, как "Switch"

  3. Имя UIViewController как «вид» или «NewView»

Что касается логики: Здесь все испортилось. Фактически вы создаете viewController с именемOfLabel, который пуст и изменяется только при нажатии кнопки. Я предполагаю, что вы нажмете эту кнопку, чтобы она изменилась. Затем на действие переключателя вы создаете другой viewController и представляете его. Затем изнутри этого нового viewController вы создаете еще один новый viewController, у которого есть пустое имяOfLabel, получите это пустое значение и поместите его во второйLabel.

Есть несколько способов, вы можете сделать, чтобы изменить secondLabel:

  1. Move nameOfLabel модели и читать его оттуда, когда вы хотите изменить secondLabel,
  2. Потому что ваш новый ViewController является ребенок ViewController, что сохраняет имяOfLabel, вы можете получить к нему доступ, вызвав [[self presentingViewController] nameOfLabel], но сначала сделайте его свойство,
  3. Пропустить имя OfLabel через назначенный инициализатор.
0

Когда представлен второй контроллер вида (NewView), он не имеет ссылки на первый контроллер представления (ViewController) и его данные.

Вот несколько предложений.

  • В современной Objective-C я бы рекомендовал использовать свойства вместо того, чтобы подвергать переменную.
  • Посмотрите на именование в целом. Например, «ViewController» не является хорошим именем.
  • Если свойство является частью внутреннего состояния класса, объявите его в расширении класса.
  • Перед тем, как представить второй контроллер представлений, установите ссылку на строку с первого контроллера представления.

Часть ViewController.m:

@interface ViewController() 
@property (copy,nonatomic) NSString *nameOfLabel; 
@end 

@implementation ViewController 

- (IBAction)Switch:(id)sender { 
    NewView *new = [[NewView alloc] initWithNibName:nil bundle:nil]; 
    new.secondLabel.text = self.nameOfLabel; 
    [self presentViewController: new animated:YES completion:NULL]; 
} 
+0

Я не уверен, что делать в последнем пункте, я только что начал Obj-C. Я использовал остальную часть кода, который вы дали, но он все еще не работал. – PappaSmalls

0

Ну, если вы хотите простой демонстрации доступа общественного Ивар, синтаксис:

view->nameOfLabel; 
    ^^ 

не дот-синтаксис:

view.nameOfLabel; 

(dot-syntax только проходит через методы доступа).

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

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