我有一个Swift框架,定义了一个结构体:

public struct CollectionTO {
    var index: Order
    var title: String
    var description: String
}

但是,我似乎不能从导入库的另一个项目中使用隐式的按成员初始化器。错误是:

'CollectionTO'不能被初始化,因为它没有可访问的初始化器

也就是说,默认的合成成员初始化器不是公共的。

var collection1 = CollectionTO(index: 1, title: "New Releases", description: "All the new releases")

我必须像这样添加我自己的init方法:

public struct CollectionTO {
    var index: Order
    var title: String
    var description: String

    public init(index: Order, title: String, description: String) {
        self.index = index;
        self.title = title;
        self.description = description;
    }
}

... 但是有没有一种方法可以做到这一点而不显式地定义一个公共init?


引用手册:

"结构类型的默认成员初始化器 如果结构的任何存储属性是私有的,则结构类型的默认成员初始化式被认为是私有的。否则,初始化器的访问级别为internal。 与上面的默认初始化式一样,如果你想在其他模块中使用一个公共结构类型时,可以用一个成员级初始化式初始化,你必须自己提供一个公共成员级初始化式,作为类型定义的一部分。”

摘自“Swift编程语言”,“访问控制”一节。


虽然不可能有默认的成员初始化式,但至少你可以通过以下步骤快速创建一个:

更新:Xcode 11及以后

正如Brock Batsell在评论中提到的,对于Xcode 11和以后的版本,你所需要的是:

右键单击类或结构名称并选择refactor -> 生成成员初始化器

Xcode 10和更早的答案

将对象临时设为类,而不是结构 保存 右键单击类名并选择refactor -> 生成成员初始化器 把它改回结构体


有时候,当你不需要初始化式时,使用它真的很烦人。如果不断地更新对象的变量,那么在3个地方(变量声明、初始化式参数和初始化式实现)更新变量就会变得非常麻烦。 对于这个问题,我使用的一个变通方法是在结构上使用一个静态变量来充当(或本质上包装)“初始化器”。例如:

struct MyStruct {
    static var empty = Self()
    static func empty(name: String) -> Self {
        .init(privateName: name)
    }

    private var identifier: String = ""
}

然后你可以像调用初始化器一样调用它(带有自动完成和所有的东西!):

func someFunction(_ value: MyStruct) { ... }

//someFunction(.init()) -> ERROR, invalid due to `private` variable
someFunction(.empty)
someFunction(.empty(name: "Dan IRL"))
let myObject = MyStruct.empty
let myObject2 = MyStruct.empty(name: "Monty Python")