Objective-C构造函数中的必需参数

时间:2012-02-13 12:42:17

标签: objective-c constructor

在尝试将我之前基于单例的全局控制器类转换为更多OOP友好依赖注入方法的过程中,该方法在需要时将所需方法从一个对象传递到另一个对象。我遇到了我的上一课在init期间使用全局对象的问题。

(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 个答案:

答案 0 :(得分:5)

是的,你的解决方案是正确的,首选方法是创建另一个以init开头的方法,并在调用super之后传递所需的初始化参数并返回self。

答案 1 :(得分:2)

这样做的现代方法是在.m中使用NS_DESIGNATED_INITIALIZER

@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

答案 2 :(得分:1)

如果它们可能是默认的FMPhysics对象(不熟悉它),那么另一个选择是init用默认的物理世界调用initWithPhysics。

例如,这是一个带有db包装器的init重载,其中默认的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;
}