Ошибка EXC_BAD_ACCESS при смене представлений с помощью PresentModalViewController - PullRequest
0 голосов
/ 09 декабря 2011

Я пытаюсь переключать представления в моем приложении, используя этот фрагмент кода:

self->variable1 = [[NSNumber alloc] initWithInt:0];
self->variable2 = [[NSMutableArray arrayWithCapacity:1];
self->variable3 = [[NSMutableArray arrayWithCapacity:1];

[self presentModalViewController:titleScreen animated:YES];

Если я закомментирую все выделенные строки переменных, код работает нормально. Если оставить только 1 строку в коде, происходит сбой с ошибкой «EXC_BAD_ACCESS». Почему это происходит? Переменные вообще не используются, просто объявлены для последующего использования. Я не получаю никаких ошибок компиляции в строках. Что я делаю не так?

UPDATE:
Спасибо всем за помощь. Я изменил способ объявления своих переменных на @ property / @ synth, чтобы очистить мой код, но это не решило проблему. После долгого возни я починил. Я изменил код из этого:

self.variable1 = [[NSNumber alloc] initWithInt:0];

к этому:

self.variable1 = [NSNumber alloc];
[self.variable1 initWithInt:0];

и это сработало! Может кто-нибудь объяснить, почему это сработало, а первая строка - нет?

Обновление:

Спасибо, Питер Хоси, что показал мне мои злые пути. На этот раз я уверен, что это исправлено. Я хранил свои переменные Releases в

-(void)release

Я не знал, что xCode выпустит, когда это необходимо. Я переместил все выпуски переменных в

-(void)Destroy

так что я могу отпустить все по моей команде. Теперь код работает. Еще раз спасибо!

Ответы [ 3 ]

1 голос
/ 09 декабря 2011

Я предлагаю объявить variable1, variable2 и variable3 в качестве свойств, а не переменных экземпляра. Затем используйте self.variable1, self.variable2 и self.variable3 для доступа к ним.

Синтаксис точки (self.variable1 и т. Д.) Использует политику управления памятью, которую вы объявили для каждого свойства; синтаксис стрелки (self->variable1 и т. д.) будет напрямую обращаться к переменным. Сбой произошел из-за того, что вы создали два массива на расстоянии, которое не оставляет вас в собственности, а затем не присвоили массивы свойству, которое их сохранит.

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


В ответ на ваши изменения:

Я изменил способ объявления своих переменных на @ property / @ synth, чтобы очистить мой код, но это не решило проблему.

Тогда что-то еще было не так.

Вы никогда не говорили много о самой проблеме. Вы сказали, что получили EXC_BAD_ACCESS, но не то, какое утверждение вызвало сбой или на каких основаниях вы обвиняли его в показанном вами коде.

Я изменил код с этого:

self.variable1 = [[NSNumber alloc] initWithInt:0];

Это правильный код. Это то, что вы должны использовать.

на это:

self.variable1 = [NSNumber alloc];
[self.variable1 initWithInt:0];

Noooo! Этот код неправильный, неправильный, неправильный на нескольких уровнях.

Методы

init (включая методы initWithWhatever:) не гарантируют возвращение того же объекта, которому вы отправили сообщение. initWithInt: NSNumber очень вероятно не .

Этот объект создает неинициализированный NSNumber объект и назначает его свойству. Затем он отправляет initWithInt: этому объекту, который вернет инициализированный объект, которым может быть , а очень вероятно будет другим объектом . Теперь вы держите неинициализированный объект (который вы попробуете использовать позже) и бросили инициализированный объект на пол.

Никогда, никогда, никогда не отправляйте alloc и init (With…) в отдельных выражениях. Всегда отправляйте их в одном выражении. Без исключений. В противном случае вы рискуете удерживать неинициализированный объект, а не инициализированный объект. В вашем случае (с NSNumbers) это почти наверняка произойдет.

Что вам следует сделать, это объявить и синтезировать сильное свойство, которому принадлежит объект NSNumber, и создать объект NSNumber в одном выражении: [[NSNumber alloc] initWithInt:] или [NSNumber numberWithInt:]. Если вы не используете ARC, вам понадобится последнее, поскольку свойство сохранит объект. Если вы используете ARC, они фактически эквивалентны.

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

1 голос
/ 09 декабря 2011

variable2 и variable3 автоматически высвобождаются до того, как вы на самом деле получите к ним доступ (предположительно) позже после представления модального представления.

Как минимум измените строки на:

self->variable2 = [[NSMutableArray arrayWithCapacity:1] retain];
self->variable3 = [[NSMutableArray arrayWithCapacity:1] retain];

или

self->variable2 = [[NSMutableArray alloc] initWithCapacity:1];
self->variable3 = [[NSMutableArray alloc] initWithCapacity:1];

variable1 должно быть в порядке.

Лучше всего использовать @property и @synthesize, чтобы вы могли использовать точечную запись:

.h

@interface MyClass : SuperClass

@property (nonatomic,retain) NSMutableArray *variable2;
@property (nonatomic,retain) NSMutableArray *variable3;

@end

.m

@implementation MyClass
@synthesize variable2,varible3;

- (void)foo {

    self.variable2 = [NSMutableArray arrayWithCapacity:1];
    self.variable3 = [NSMutableArray arrayWithCapacity:1];

}

@end
0 голосов
/ 09 декабря 2011

По умолчанию все переменные экземпляра в target-c имеют защищенную область видимости. Поэтому, если вы явно не объявили их общедоступными в файле интерфейса как:

@interface MYClass {

@public
    NSNumber *variable1;
    NSMutableArray *variable2;
    NSMutableArray *variable3;
}
//...
@end

тогда они не будут доступны с помощью оператора разыменования структуры. Это, вероятно, причина этих ошибок EXC_BAD_ACCESS.

...