2012-04-27 2 views
5

Кажется, что в примере кода книги init всегда определяется так, чтобы было важно проверить, существует ли возможность существования self.В Objective-C, как иметь дело с [[myView alloc] init], возвращающим нуль?

-(id) init { 

    self = [super init]; 
    if (self) { 
     // initialize 
    } 
    return self; 
} 

Однако по возвращении ни один из кодов вообще не проверяет, существует ли объект. Но нужно ли его проверять и как его можно обрабатывать? Если объект не может существовать, значит ли это, что система серьезно отстает от памяти, и даже появление сообщения об ошибке также невозможно?

+0

Это на самом деле довольно хороший вопрос. Я знаю, что я никогда не проверяю, не получил ли я что-то из результата такой функции, я просто предполагаю, что работа alloc/init работала (если только не работала с чем-то, что принимает & error, что представляет собой что-то, что может привести к сбою). Очень интересный вопрос. – RonLugge

+0

Возможный дубликат [In Objective-C, почему я должен проверить, является ли self = \ [super init \] не нулем?] (Http://stackoverflow.com/questions/1287950/in-objective-c-why-should- i-check-if-self-super-init-is-not-nil) – omz

ответ

4

Однако по возвращении ни один из кодов вообще не проверяет, существует ли объект. Но нужно ли его проверять и как его можно обрабатывать?

Как правило, обработка ошибок игнорируется подклассами, когда возвращается nil. Обработка ошибок обычно предоставляется вызывающему абоненту, когда возвращается nil. Как показано в идиоматической -init:

- (id)init { 
    self = [super init]; 
    if (self) { 
    // initialize 
    } 
    return self; 
} 

А также, если основание перераспределяет в initself, то self переназначается (self = [super init];). прекрасно работает.

Если вы не назначить self результату инициализаторе super «s или, если вы не проверить nil, то вы можете быть держась за висящей/высвобождены указатель (EXC_BAD_ACCESS), и вы не можете инициализировать Ивар (вы фактически назначили бы их другому региону, если не было встречено EXC_BAD_ACCESS).

Два случая более подробно:

не удается назначить самостоятельно

- (id)init { 
    [super init]; 
    if (self) { 
    // self was not reassigned. if super returned an object other 
    // than self, then our ivar would be freed, reused, or sitting 
    // in an autorelease pool, and the returned instance's ivar 
    // would not be assigned -- we wouldn't know the address. 
    ivar = 1; 
    } 
    return self; 
} 

Сбой для проверки нулевой

- (id)init { 
    self = [super init]; 
    // super returned nil. ivar is an invalid region: 
    ivar = 1; 
    return self; 
} 

и да, я видел оба эти.


Если объект не может существовать, значит ли система серьезно из памяти, и даже появляться сообщение об ошибке будет также невозможно?

Совсем нет. Многие инициализаторы возвращают nil, чтобы сказать, что «не может сделать в этом контексте», или если есть простая ошибка параметра.

+0

Извините, я не понимаю, как у вас будет обвисший указатель, если вы не будете проверять нуль. Если вы не будете проверять нуль, тогда вы фактически отправляете сообщения в нуль, если придет нуль, и они будут проигнорированы. – borrrden

+0

А, я вижу, что это фактически вторая часть (переопределяющая себя), о которой вы говорите. Nevermind ^^; – borrrden

+0

@borrrden я вижу, что вы видели обновление, которое я сделал для вас :) Да, обмен сообщениями * может * быть безопасным, если бы я был ноль, и вы были в сообщении в своем инициализаторе. однако инициализация и dealloc являются особыми частично сконструированными состояниями. люди утверждают, что обе стороны, но прямая инициализация - это, как правило, более безопасный способ инициализации объекта, а не использование аксессуаров в init/dealloc. Невозможно проверить, что ноль также является риском, как показано. – justin

3

значит, что система серьезно из памяти

No. Неспособность выделить память, как правило, вызывают + Alloc, чтобы потерпеть неудачу, не -init.

В действительности, это очень необычно для метода init без аргументов. Как правило, методы init могут возвращать nil, если вы передали недопустимые аргументы, например, NinitString -initWithContentsOfFile: может возвращать nil, если ему не удалось загрузить содержимое пути к файлу, с которым он должен был инициализироваться.

Возможно, что-то, что вы хотите проверить, если вы знаете о значительной возможности отказа от инициализации, в противном случае вам следует просто использовать этот объект.

+0

Кроме того, на iOS, если система серьезно отстает от памяти, вы будете отброшены. –

+0

@KevinBallard, да, приложение будет убито до сбоя памяти. И в OS X есть такое огромное пространство виртуальной памяти в 64 бит, что довольно неплохо, что у приложения будет нехватка памяти. – joerick

+0

iOS будет использовать любую флэш-память в качестве виртуальной памяти? (например, если iPhone на 16 ГБ имеет 3 ГБ бесплатно) ... однако, мой iPhone настолько полон песен из-за автоматической загрузки, что теперь доступно только 20 МБ. –