首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >带有参数的Singleton和init

带有参数的Singleton和init
EN

Stack Overflow用户
提问于 2015-02-10 10:36:52
回答 6查看 34.4K关注 0票数 35

我想在我的类中使用单例模式,它有一个带有参数的私有init。它还有一个名为setup的类函数,它配置和创建共享实例。我的目标-c代码是:

代码语言:javascript
复制
@interface MySingleton: NSObject

+ (MySingleton *)setup:(MyConfig *)config;
+ (MySingleton *)shared;
@property (readonly, strong, nonatomic) MyConfig *config;

@end


@implementation MySingleton

static MySingleton *sharedInstance = nil;

+ (MySingleton *)setup:(MyConfig *)config {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] initWithConfig:config];
    });

    // Some other stuff here

    return sharedInstance;
}

+ (MySingleton *)shared {
    if (sharedInstance == nil) {
        NSLog(@"error: shared called before setup");
    }
    return sharedInstance;
}

- (instancetype)initWithConfig:(RVConfig *)config {
    self = [super init];
    if (self) {
        _config = config;
    }
    return self;
}

@end

我被斯威夫特困住了:

代码语言:javascript
复制
class Asteroid {
    var config: ASTConfig? // This actually should be read-only

    class func setup(config: ASTConfig) -> Asteroid {
        struct Static {
            static let instance : Asteroid = Asteroid(config: config)
        }

        return Static.instance
    }

    class var shared: Asteroid? {
        // ???
    }

    private init(config: ASTConfig) {
        self.config = config
    }
}

我想我还在用目标-c的方式思考,无法用斯威夫特来理解它。有什么帮助吗?

EN

Stack Overflow用户

发布于 2016-10-26 18:23:45

您可以通过创建static sharedInstance属性private并使用方法返回现有实例(可选地更改其属性值)或初始化新实例和设置其属性值来定义一个或多个参数的单例。例如,我还将您的config属性设置为只读:

代码语言:javascript
复制
typealias ASTConfig = String

class Asteroid  {

    private static var sharedInstance: Asteroid!

    var config: ASTConfig?

    private init(config: ASTConfig?) {
        self.config = config
        Asteroid.sharedInstance = self
    }

    static func shared(config: ASTConfig? = "Default") -> Asteroid {
        switch sharedInstance {
        case let i?:
            i.config = config
            return i
        default:
            sharedInstance = Asteroid(config: config)
            return sharedInstance
        }
    }
}

let asteroidA = Asteroid.shared()

asteroidA.config // Default

let asteroidB = Asteroid.shared(config: "B")

asteroidA.config // B

通过将config属性的setter定义为private,可以使其属性只读.

代码语言:javascript
复制
private(set) var config: ASTConfig?

...but调用shared(config:)的人仍然能够更改配置。为了防止这种情况,您需要将shared(config:)作为抛出方法:

代码语言:javascript
复制
typealias ASTConfig = String

class Asteroid  {

    enum E : Error {
        case config(message: String)
    }

    private static var sharedInstance: Asteroid!

    private(set) var config: ASTConfig?

    private init(config: ASTConfig?) {
        self.config = config
        Asteroid.sharedInstance = self
    }

    static func shared(config: ASTConfig? = nil) throws -> Asteroid {
        switch (sharedInstance, config) {
        case let (i?, nil):
            return i
        case _ where sharedInstance != nil && config != nil:
            throw E.config(message: "You cannot change config after initialization!")
        case let (nil, c?):
            sharedInstance = Asteroid(config: c)
            return sharedInstance
        default:
            sharedInstance = Asteroid(config: "Default")
            return sharedInstance
        }
    }
}

let asteroidA = try! Asteroid.shared(config: "A")

asteroidA.config // A

let asteroidB = try! Asteroid.shared()

asteroidB.config // A

do {
    let asteroidC = try Asteroid.shared(config: "C")
} catch {
    print(error) // "config("You cannot change config after initialization!")\n"
}

//asteroidB.config = "B" // Error: Cannot assign to property: 'config' setter is inaccessible
票数 5
EN
查看全部 6 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28429544

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档