¿Cómo puedo hacer público el initialiser memberwise, por defecto, para estructuras en Swift?

164

Tengo un marco rápido que define una estructura:

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

Sin embargo, parece que no puedo usar el inicializador sabio implícito de otro proyecto que importa la biblioteca. El error es 'CollectionTO' no se puede inicializar porque no tiene inicializadores accesibles. es decir, no está dando al usuario inicial implícito sabio implícito predeterminado la palabra clave pública.

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

Tengo que agregar mi propio método init así:

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

}

... pero preferiría no hacerlo si hay otra manera de que alguien lo sepa?

bandejapaisa
fuente

Respuestas:

269

Citando el manual:

"Inicializadores predeterminados de Memberwise para tipos de estructura El inicializador predeterminado de Memberwise para un tipo de estructura se considera privado si alguna de las propiedades almacenadas de la estructura es privada. De lo contrario, el inicializador tiene un nivel de acceso interno.

Al igual que con el inicializador predeterminado anterior, si desea que un tipo de estructura pública se pueda inicializar con un inicializador miembro cuando se usa en otro módulo, debe proporcionar un inicializador público miembro como parte de la definición del tipo ".

Extracto de "El lenguaje de programación Swift" , sección "Control de acceso" .

bandejapaisa
fuente
289
Bueno, eso es molesto. :(
Dan Loewenherz
77
[ github.com/apple/swift-evolution/blob/master/proposals/… dice: "Citando a Chris Lattner: El comportamiento inicializador predeterminado de Swift tiene al menos estas deficiencias (IMO): 2) Control de acceso + el inicio de miembro a menudo requiere que lo implemente usted mismo ". Entonces, tal vez es solo una deficiencia que existe sin ninguna razón en particular. No se pudieron encontrar más referencias sobre esto.
Jano
8
@DanLoewenherz Sí, es inconveniente. La razón es: “Un tipo público por defecto tiene miembros internos, no miembros públicos. Si desea que un miembro de tipo sea público, debe marcarlo explícitamente como tal. Este requisito asegura que la API pública para un tipo es algo que opta por publicar, y evita presentar el funcionamiento interno de un tipo como API pública por error ". Extracto de: Apple Inc. "El lenguaje de programación Swift". iBooks itun.es/gb/jEUH0.l
bandejapaisa
18
Sería bueno que una directiva de compilación anulara el comportamiento predeterminado y lo hiciera público.
bandejapaisa
9
Interna es una elección terrible para un defecto, en mi opinión. Básicamente garantiza que se encontrará con problemas inesperados al hacer referencia externa a un módulo por primera vez. ¿Por qué no predeterminar todo a privado, para que podamos saber de inmediato cuando algo no tiene el nivel de acceso correcto y luego decidir si debería ser público o interno?
devios1
72

Si bien no es posible tener el inicializador predeterminado para miembros, al menos puede hacer uno rápidamente con los siguientes pasos:

  1. Haga que el objeto sea una clase temporalmente en lugar de una estructura
  2. Salvar
  3. Haga clic derecho en el nombre de la clase y elija refactorizar -> Generar inicializador de Memberwise
  4. Vuelva a cambiarlo a una estructura
JP Aquino
fuente
brillante. No puedo agradecerles lo suficiente como para evitar esta deficiencia rápida
Anton Tropashko
1
Funciona y también motiva a usar clases en lugar de estructuras youtube.com/watch?v=_V2sBURgUBI
Isaac Carol Weisberg
Eso es un súper consejo!
Peymankh
66
¡A partir de Xcode 11, también puede usar Generate Memberwise Initializer en estructuras!
Brock Batsell
¡¡¡Fantástico!!! ¡No es la respuesta correcta, pero es un muy buen consejo! ¡Me ayudo mucho!
GuiOS
3

Hasta que Apple cambie esto y lo haga menos molesto, puede usar https://github.com/Bouke/SwiftInitializerGenerator (o cualquier otro) esto para la creación de inicializadores públicos. Entonces será menos trabajo. Lo probé y funciona. Xcode versión 10.0, High Sierra 10.13.6

Zaporozhchenko Oleksandr
fuente
1

Ahora tenemos una gema de rubí 💎 para analizar un archivo completo de modelo de datos rápidos, línea por línea, y agregar modificadores de acceso público, inicializadores predeterminados públicos y otros elementos en un archivo rápido de salida generado automáticamente.

Esta gema se llama swift_republic

Consulte la siguiente documentación para ejecutar esta gema:

https://github.com/mehul90/swift_republic

Mehul Parmar
fuente
1
¡Impresionante solución! Ya creé un contenedor para swift_republicy funciona bien.
Md Shahed Hossain