swift 结构初始值设定项由于其自身文件的私有保护级别而不可访问

smdnsysy  于 2023-01-12  发布在  Swift
关注(0)|答案(4)|浏览(152)

使用Swift 4,我在同一个文件中定义了两个结构体,其中一个是私有的,所以这个文件是唯一可以访问它的文件,而且我依赖于结构体的默认/合成初始化器,也就是说,我没有显式定义一个:

private struct A {
  private let string: String
  ...
}

struct B {
  func foo() {
    let a = A(string: "bar")
    ...
  }
}

但是,这将无法编译,并出现以下错误:
由于“private”保护级别,无法访问“A”初始值设定项
我不希望其他文件可以访问A,所以我尝试将其设置为fileprivate(在本场景中应该等效于private),但还是会发生相同的编译错误(并且它仍然抱怨保护级别为private)。
有没有办法保留这个结构体fileprivate,同时仍然获得一个公开所有未初始化属性的合成初始化器?例如A.init(string:)

s6fujrry

s6fujrry1#

原来“private access level”的抱怨是针对init初始化器的,而不是针对结构体的。初始化器的访问级别只与“最难访问”的示例变量一样可访问。
如果我将string示例变量设置为private以外的任何变量,错误就会消失:

private struct A {
  let string: String
  // synthesized initializer:
  // init(string: String)
}

因此,假定B现在可以读取Astring,它也可以访问A的初始化器。
如果A有另一个private属性,那么它的初始化器也会变成private

private struct A {
  let string: String
  private let int: Int
  // synthesized initializer:
  // private init(string: String, int: Int)
  ...
}
hiz5n14c

hiz5n14c2#

你可以定义初始化器。它将帮助你保持这个结构private。主要问题是private let string编译器自动添加私有访问级别private init(string: String)的初始化器。
为了修复,您必须定义自己的初始化器

private struct A {
    private let string: String

    fileprivate init(string: String) {
        self.string = string
    }

    func foo() {}
}

struct B {
    func bar() {
        A(string: "baz").foo()
    }
}

或者你可以使用fileprivate访问级别来访问string属性。在这种情况下你不需要初始化器。

private struct A {
    fileprivate let string: String

    func foo() {}
}

struct B {
    func bar() {
        A(string: "baz").foo()
    }
}
qni6mghb

qni6mghb3#

下面是解决使用SwiftUI结构体时可能发生的错误的另一种方法。
给定此代码将产生相同的错误,因为变量未初始化或编译器不知道该变量是否保证具有值。

struct MyView: View {
    // Compiler: ¯\_(ツ)_/¯ 
    // initializer is inaccessible due to 'private' protection level
    private var rows: [Int]

    var body: some View {
        Text("Some text")
    }
}

因此,您可以将其设置为可选的、未 Package 的或用值初始化的。

struct MyView: View {
    // Initialized
    private var rows = [Int]()

    var body: some View {
        Text("Some text")
    }
}

当示例化MyView()时,编译器不会抱怨。

struct MyView_Previews: PreviewProvider {
    static var previews: some View {
        MyView()
    }
}
hmmo2u0o

hmmo2u0o4#

我用过

private let s: String = "Some value"

这对我很有效。

相关问题