Обязательные параметры в конструкторах Objective-C - PullRequest
3 голосов
/ 13 февраля 2012

В процессе попытки преобразовать мои классы глобального контроллера на основе синглтона в более удобный ООП-метод внедрения зависимостей, передавая требуемые методы из одного объекта в другой по мере необходимости. Я столкнулся с проблемой, когда мой предыдущий класс использовал глобальный объект во время инициализации.

(id)init 
{
    self = [super init];
    if (self) 
    {
        [self setUpPhysicsWithWorld:FMPresenter.physics.world];
    }
    return self;
}

Где FMPresenter.physics возвращает физический объект-одиночка. Поскольку мой объект не может быть правильно создан без объекта Physics, вызов init недопустим. Я видел это используется:

(id) init 
{
    NSAssert(NO, @"init not allowed");
    [self release];
    return nil; 
}

(id) initWithPhysics:(FMPhysics*)physics 
{
    self = [super init];
    if (self) {
        [self setUpPhysicsWithWorld:physics.world];
    }
    return self;
}

Является ли это предпочтительным методом для принудительного применения параметров конструктора в Objective-C?

Ответы [ 3 ]

5 голосов
/ 13 февраля 2012

Да, ваше решение верное, предпочтительным способом является создание другого метода, который начинается с init и которому вы передаете необходимые параметры инициализации и возвращаете self после вызова super.

2 голосов
/ 04 ноября 2014

Современный способ сделать это - использовать NS_DESIGNATED_INITIALIZER в вашем .m:

@interface FMPresenter
- (instancetype)initWithPhysics:(FMPhysics*)physics NS_DESIGNATED_INITIALIZER;
@end

Также обратите внимание на использование instancetype, который теперь предпочтительнее, чем id.

https://developer.apple.com/library/mac/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.html#//apple_ref/doc/uid/TP40014150-CH1-SW8

1 голос
/ 13 февраля 2012

Если они могут быть объектом FMPhysics по умолчанию (не знакомым с ним), то для init можно вызвать initWithPhysics с физическим миром по умолчанию.

Например, вот перегрузка init с оберткой db, когда init по умолчанию создает в памяти db, что является хорошим значением по умолчанию.

- (id)init
{
    sqlite3 *db;
    sqlite3_open(":memory:", &db);
    return [self initWithDatabase:db];
}

- (id)initWithDatabase:(sqlite3*)database
{
    self = [super init];
    if (self)
    {
        _sqlite3 = database;      
    }

    return self;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...