#iphone #objective-c
#iPhone #objective-c
Вопрос:
Я столкнулся с ситуацией в Objective-C, когда я пытаюсь получить доступ к переменной объекта через другой объект. Классы (упрощенный):
A.h
@interface A : NSObject {
NSMutableArray *someStuff;
}
@property (nonatomic, retain) NSMutableArray *someStuff;
@end
A.m
@implementation A
@synthesize someStuff;
// blah, blah, blah
Затем, поскольку я создаю приложение для iPhone, есть делегат приложения, который содержит переменную этого типа объекта:
AppDelegate.h
@interface AppDelegate : NSObject <UIApplicationDelegate> {
A *aPtr;
}
@property (nonatomic, retain) A *aPtr;
@end
AppDelegate.m
@implementation AppDelegate
@synthesize aPtr;
// blah, blah, blah
Затем, в другом классе (в этом контроллере представления), я пытаюсь получить доступ к ‘someStuff’ таким образом:
AViewController.m
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSMutableArray *someArray = appDelegate.aPtr.someStuff;
Итак, проблема в том, что это прекрасно работает. Я думаю, что я слишком большой любитель Java, чтобы понять, почему это не сработает. Кто-нибудь может просветить меня?
Большое спасибо,
Крейг
Ответ №1:
Вам нужно инициализировать это таким образом
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
NSMutableArray *someArray = appDelegate.someArray;
Это решит вашу проблему…..
Комментарии:
1. неправильно, приведение не требуется, приведенный выше код не должен прерываться (и не прерывается — просто проверил это)
2. Хорошо, я попробовал это. Компилятор жалуется, что someStuff не является объектом в AppDelegate (которым он, конечно, не является). Ошибка компилятора, которую я обычно получаю, заключается в том, что someStuff не является объектом A. Все еще застрял.
3. Итак, у вас ошибка компилятора, а не ошибка времени выполнения? Вы должны были указать это. Убедитесь, что у вас есть все включаемые на месте, чтобы компилятор знал, какие атрибуты какому классу принадлежат, и что у вас нет более одной версии класса A, которую вы могли бы включить, одна без someStuff .
4. Я думаю, вы, должно быть, импортируете свой делегат в классе .m и не объявляете класс своего делегата в классе .h. Объявите свой делегат в .h как @Class yourdelegate и импортируйте его в класс .m.
Ответ №2:
Крейг,
appDelegate.aPtr
вернется null
. поскольку он еще не инициализирован, и когда вы пытаетесь получить доступ к какому-либо члену null
объекта (в Java NULLPointerException
).Его поведение соответствует ожиданиям.(это прекрасно работает).
Спасибо,
Ответ №3:
Равин прав. Определение класса определяет IVAR и свойства для класса, поэтому вы определили iVar, aPtr
который ссылается на объект типа A
. Однако вы не выделили и не инициализировали этот объект.
Примером использования инициализации по умолчанию может быть `aPtr = [[A alloc] init]’.
Комментарии:
1. Извините, я должен был указать, что я инициализировал aPtr. Ваш ответ правильный, учитывая, что я этого не упоминал. Но он инициализирован, так что есть еще кое-что, чего мне не хватает.
2. Это нормально, но принятый вами ответ на самом деле не решает вашу проблему. 1) Приведение не требуется, 2) Вы не объявили iVar / property
someArray
и 3) он не перешел на следующий уровень косвенности, который вы сделали в коде, который вы опубликовали, чтобы перейти кaPtr.someStuff
. Пока вы счастливы, рад, что у вас все работает.
Ответ №4:
Все это звучит подозрительно, поскольку в ObjC вам разрешено отправлять сообщения в ноль без проблем, а свойства — это просто оцифрованные методы. Например, вы можете
view = nil;
view.hidden = NO;
и это не взрывается, это просто ничего не делает.
Итак, поскольку AppDelegate.aPtr.someStuff просто
[[appDelegate aPtr] someStuff];
и [AppDelegate aPtr] ничего не делает и возвращает nil, поэтому должно быть безопасно вызывать [[AppDelegate aPtr] someStuff] без проблем, но и без каких-либо результатов.
Итак, хотя это проблема с использованием объектов, которые не были инициализированы (что чаще всего следует делать в назначенном конструкторе соответствующего объекта), поскольку вы не получаете ожидаемых результатов, в моем понимании «отправки сообщения на ноль» в ObjC это не должно привести к сбою. Если это так, то либо я упускаю суть, либо проблема вызвана чем-то другим, а не этим вызовом.
Редактировать
только что проверено: если вообще не инициализировано, все работает, как я объяснил: ObjC разрешает отправлять сообщения с нулевым значением:
A *aPtr = appDelegate.aPtr;
NSMutableArray *someArray = aPtr.someStuff;
NSLog(@"%@", someArray);
или
NSMutableArray *someArray = appDelegate.aPtr.someStuff;
NSLog(@"%@", someArray);
оба не прерываются и не выводят null.
Если вы правильно инициализируете A, но не инициализируете someStuff в A, он все равно не прерывается, но выводит null. Проблема может заключаться в том, что вы инициализируете aPtr для класса, отличного от A, и в этом случае вы получаете нераспознанное исключение селектора (вы должны быть в состоянии увидеть его в журнале ошибок) и сбой программы.