Como tornar público o inicializador de membros, por padrão, para estruturas no Swift?

164

Eu tenho uma estrutura rápida que define uma estrutura:

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

No entanto, não consigo usar o inicializador sábio de membro implícito de outro projeto que importa a biblioteca. O erro é 'CollectionTO' não pode ser inicializado porque não possui inicializadores acessíveis. ou seja, não está dando ao inicializador implícito padrão do membro implícito a palavra-chave pública.

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

Estou tendo que adicionar meu próprio método init da seguinte forma:

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;
    }

}

... mas prefiro que não, se houver outra maneira de alguém saber?

bandejapaisa
fonte

Respostas:

268

Citando o manual:

"Inicializadores padrão para membros de tipos de estrutura O inicializador padrão para membros de um tipo de estrutura é considerado privado se alguma das propriedades armazenadas da estrutura for privada. Caso contrário, o inicializador terá um nível de acesso interno.

Como no inicializador padrão acima, se você deseja que um tipo de estrutura pública seja inicializável com um inicializador membro a membro, quando usado em outro módulo, você deve fornecer um inicializador público membro a membro como parte da definição do tipo ".

Trecho de "A linguagem de programação Swift" , seção "Controle de acesso" .

bandejapaisa
fonte
288
Bem, isso é chato. :(
Dan Loewenherz
7
[ github.com/apple/swift-evolution/blob/master/proposals/… diz: “Citando Chris Lattner: O comportamento padrão do inicializador de membros do Swift tem pelo menos essas deficiências (IMO): 2) Controle de acesso + o init do membro frequentemente requer que você o implemente ”. Então, talvez seja apenas uma deficiência que existe sem nenhuma razão em particular. Não foi possível encontrar mais referências sobre isso.
Jano
8
@DanLoewenherz Sim, é inconveniente. A lógica é: “Um tipo público é o padrão para ter membros internos, não membros públicos. Se você deseja que um membro do tipo seja público, deve marcá-lo explicitamente como tal. Esse requisito garante que a API voltada ao público para um tipo seja algo que você opta por publicar e evita apresentar por engano o funcionamento interno de um tipo como API pública. ” Trecho de: Apple Inc. “A linguagem de programação Swift”. iBooks. itun.es/gb/jEUH0.l
bandejapaisa #
18
Uma diretiva de compilador seria legal substituir o comportamento padrão e torná-lo público.
precisa saber é o seguinte
9
Interno é uma péssima escolha para um padrão, IMO. Basicamente, garante que você tenha problemas inesperados ao fazer referência a um módulo externamente pela primeira vez. Por que não padronizar tudo para privado, para que possamos saber imediatamente quando algo não recebe o nível de acesso correto e depois decidir se deve ser público ou interno?
precisa
72

Embora não seja possível ter o inicializador padrão para membros, pelo menos, você pode fazer um rapidamente com as seguintes etapas:

  1. Tornar o objeto uma classe temporariamente em vez de uma estrutura
  2. Salve 
  3. Clique com o botão direito do mouse no nome da classe e escolha refatorar -> Gerar Inicializador Memberwise
  4. Altere de volta para uma estrutura
JP Aquino
fonte
brilhante. Não posso lhe agradecer o suficiente para contornar essa deficiência rápida
Anton Tropashko
1
Obras e também motiva realmente usar as classes em vez de estruturas youtube.com/watch?v=_V2sBURgUBI
Isaac Carol Weisberg
Essa é uma super dica !!
Peymankh 18/01
6
A partir do Xcode 11, você também pode usar o Generate Memberwise Initializer em estruturas!
Brock Batsell 24/04
Fantástico!!! Não é a resposta certa, mas é uma dica muito boa! Me ajudou muito!
GuiOS
3

Até a Apple mudar isso e torná-lo menos irritante, você pode usar https://github.com/Bouke/SwiftInitializerGenerator (ou qualquer outro) para criar criadores de inicializadores públicos. Portanto, será menos trabalho. Tentei e funciona. Xcode Versão 10.0, High Sierra 10.13.6

Zaporozhchenko Oleksandr
fonte
1

Agora temos um ruby ​​gem 💎 para analisar um arquivo de modelo de dados rápido completo, linha por linha, e adicionar modificadores de acesso público, inicializadores padrão por membros públicos e outras coisas em um arquivo rápido de saída gerado automaticamente.

Essa gema é chamada swift_republic

Consulte a seguinte documentação para executar esta gema:

https://github.com/mehul90/swift_republic

Mehul Parmar
fonte
1
Solução impressionante !! Eu já criei um invólucro swift_republice estou funcionando bem.
Md Shahed Hossain