Cocoa: доступ к @public NSArray после его обновления из одного класса в другой

#xcode #macos #cocoa #xcode4 #osx-lion

#xcode #macos #cocoa #xcode4 #osx-lion

Вопрос:

Как я могу получить доступ @public NSArray к нему или NSMutableArray после его обновления? Из одного класса в другой?

Я могу получить к нему доступ с помощью вызова -(id)init .. при запуске программы, но если я захочу обновить ее позже, я получаю ноль. В чем проблема?

Простой пример кода:

MyFirstClass.h

 #import <Foundation/Foundation.h>

@interface MyFirstClass : NSObject
{
@public

    NSArray *testArray;

}

-(IBAction)Button:(id)sender;

@end
  

MyFirstClass.m

 #import "MyFirstClass.h"

@implementation MyFirstClass
- (id)init {
if (self = [super init]) {

    //I can take this Array from here

    //testArray = [NSArray arrayWithObjects: @"first", @"second", @"third", nil];

}
    return self;
}

-(IBAction)Button:(id)sender {

    //How take this Array?

    testArray = [NSArray arrayWithObjects: @"first", @"second", @"third", nil];

}

@end
  

SimpleClass.h

 #import <Foundation/Foundation.h>
#import "MyFirstClass.h"

@interface SimpleClass : NSObject
{
    MyFirstClass *other;
}

-(IBAction)ButtonGet:(id)sender;

@end
  

SimpleClass.m

 #import "SimpleClass.h"
#import "MyFirstClass.h"

@implementation SimpleClass

-(IBAction)ButtonGet:(id)sender {

    other = [[MyFirstClass alloc] init];     

    if(other->testArray) {
        NSLog(@"Working!");
    }
    else { NSLog(@"Not working!"); }

}

@end
  

Созданный пример имеет две кнопки в *.xib. Одна кнопка с именем «Button» (MyFirstClass) и другая «ButtonGet» (SimpleClass). Поэтому при запуске программы нужно нажать «Button», а затем «ButtonGet», после этого NSLog должен написать «Работает!», Если он получает testArray, а если нет — «Не работает!». Он всегда показывает «Не работает!».

Комментарии:

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

2. Спасибо за ваш комментарий, я не использую сборку мусора, я использую ручное управление памятью.

3. Введите точку останова awakeFromNib , а оттуда щелкните правой кнопкой мыши testArray на панели отладчика и выберите «Наблюдать за переменной». Таким образом, при следующем изменении вашей переменной отладчик приостановит вашу программу.

4. @zneak извините, я допустил ошибку, это не работает с awakeFromNib .. Это только wotks с — (id)init {…} . Может быть, вы знаете почему? может быть, что-то не так с возвратом?

Ответ №1:

Добро пожаловать в Objective C! Если вы чувствуете себя перегруженным и хотели бы прочитать некоторые вводные материалы, пожалуйста, взгляните на ссылки в превосходной карточке Питера Хоси «Полезные ссылки на какао / Cocoa Touch«.

Вы создаете MyFirstClass экземпляр в -[SimpleClass ButtonGet:] , и поскольку его testArray член явно не назначен in -[MyFirstClass init] , он (правильно) инициализируется нулем. Он останется таким навсегда, если вы не назначите ему что-то еще, но вы никогда этого не сделаете. (Вы назначаете ему только in [MyFirstClass Button:] , но никогда не вызываете этот метод.)

Другие вещи, которые следует учитывать:

  • Ручное управление памятью требует, чтобы вы знали правила управления памятью Cocoa и постоянно учитывали их при написании кода. Например, вам нужно сохранить результат [NSArray arrayWithObjects:] , когда вы присваиваете его переменной-члену, и освободить его -[MyFirstClass dealloc] . Аналогично, вам нужно освободить other объект внутри -[SimpleClass dealloc] .

  • Гораздо удобнее использовать свойства (объявленные с помощью) вместо прямого обращения к переменным-членам другого класса. @property

  • Пожалуйста, подумайте о том, чтобы следовать рекомендациям по кодированию Cocoa и начинать имена методов со строчной буквы. Это позволяет вашему коду лучше соответствовать системным API-интерфейсам и значительно упрощает его чтение другими людьми.

Комментарии:

1. Большое вам спасибо за ваш ответ. Что вы имеете в виду, говоря «назначить ему что-то еще», можете ли вы привести мне пример, как это сделать? Я вызываю это при нажатии кнопки, нет?

2. Вы присваиваете что-то переменной-члену с помощью оператора присваивания ( = ) — вы уже написали код, в котором это делается -[MyFirstClass Button:] . Однако этот код никогда не выполняется в вашем примере. Чтобы вызвать метод, вы можете (например) вставить инструкцию [other Button:nil]; -[SimpleClass ButtonGet] после создания MyFirstClass объекта, но перед проверкой testArray . Есть ли кнопка? Вы не упомянули ни одной кнопки в своем вопросе.

3. Есть две кнопки -(IBAction) Button: и -(IBAction) ButtonGet:, извините, я не упомянул об этом. Итак, я выполняю этот код при нажатии кнопки «Button», нет? И из другого класса другая кнопка «ButtonGet»

4. Мой пример сценария: созданный пример приложения имеет две кнопки в *.xib. Одна кнопка с именем «Button» (MyFirstClass) и другая «ButtonGet» (SimpleClass). Поэтому при запуске программы нужно нажать «Button», а затем «ButtonGet», после этого NSLog должен написать «Работает!», Если он получает testArray, а если нет — «Не работает!». Он всегда показывает «Не работает!».

5. Введите точку останова или NSLog, -[MyFirstClass Button:] чтобы убедиться, что он действительно выполняется — вероятно, он неправильно подключен в xib. Вам также необходимо исправить проблему с нераспределенным членом, иначе testArray он будет освобожден почти сразу, и у вас будет указатель, указывающий в никуда.