Wie kann ich den memberwise-Initialisierer standardmäßig für Strukturen in Swift veröffentlichen?


164

Ich habe ein schnelles Framework, das eine Struktur definiert:

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

Ich kann jedoch nicht den impliziten Element-Initialisierer aus einem anderen Projekt verwenden, das die Bibliothek importiert. Der Fehler ist, dass 'CollectionTO' nicht initialisiert werden kann, da keine zugänglichen Initialisierer vorhanden sind. Das heißt, es gibt dem standardmäßigen impliziten Element-Initialisierer nicht das öffentliche Schlüsselwort.

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

Ich muss meine eigene Init-Methode wie folgt hinzufügen:

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

}

... aber ich möchte lieber nicht, ob es einen anderen Weg gibt, den jemand kennt?

Antworten:


268

Zitat des Handbuchs:

"Standardinitialisierer für Mitglieder für Strukturtypen Der Standardinitialisierer für Mitglieder für einen Strukturtyp wird als privat betrachtet, wenn eine der gespeicherten Eigenschaften der Struktur privat ist. Andernfalls verfügt der Initialisierer über eine interne Zugriffsebene.

Wie beim obigen Standardinitialisierer müssen Sie, wenn ein öffentlicher Strukturtyp bei Verwendung in einem anderen Modul mit einem Mitgliedsinitialisierer initialisiert werden soll, selbst einen öffentlichen Mitgliedsinitialisierer als Teil der Typdefinition bereitstellen. "

Auszug aus "The Swift Programming Language" , Abschnitt "Access Control" .


283
Das ist nervig. :(
Dan Loewenherz

7
[ github.com/apple/swift-evolution/blob/master/proposals/… sagt: „Zitat von Chris Lattner: Das standardmäßige Initialisierungsverhalten von Swift in Bezug auf Mitglieder weist mindestens diese Mängel auf (IMO): 2) Zugriffskontrolle + Init in Bezug auf Mitglieder häufig erfordert, dass Sie es selbst implementieren “. Vielleicht ist es nur ein Mangel, der ohne besonderen Grund besteht. Es konnten keine weiteren Referenzen dazu gefunden werden.
Jano

8
@ DanLoewenherz Ja, das ist unpraktisch. Das Grundprinzip lautet: „Ein öffentlicher Typ hat standardmäßig interne Mitglieder, keine öffentlichen Mitglieder. Wenn Sie möchten, dass ein Typmitglied öffentlich ist, müssen Sie es explizit als solches markieren. Diese Anforderung stellt sicher, dass Sie sich für die Veröffentlichung der öffentlich zugänglichen API für einen Typ entscheiden, und vermeidet, dass die internen Funktionen eines Typs versehentlich als öffentliche API dargestellt werden. “ Auszug aus: Apple Inc. "Die schnelle Programmiersprache". iBooks. itun.es/gb/jEUH0.l
Bandejapaisa

18
Eine Compiler-Direktive wäre hilfreich, um das Standardverhalten zu überschreiben und öffentlich zu machen.
Bandejapaisa

9
Intern ist eine schreckliche Wahl für einen Standard, imo. Grundsätzlich wird garantiert, dass Sie beim ersten externen Referenzieren eines Moduls auf unerwartete Probleme stoßen. Warum nicht alles auf privat setzen, damit wir sofort erkennen können, wenn etwas nicht die richtige Zugriffsebene hat, und dann entscheiden, ob es öffentlich oder intern sein soll?
Devios1

71

Obwohl es nicht möglich ist, den Standardinitialisierer für Mitglieder zu verwenden, können Sie mit den folgenden Schritten schnell einen erstellen:

  1. Machen Sie das Objekt vorübergehend zu einer Klasse anstelle einer Struktur
  2. sparen
  3. Klicken Sie mit der rechten Maustaste auf den Klassennamen und wählen Sie Refactor -> Memberwise Initializer generieren
  4. Ändern Sie es wieder in eine Struktur

brillant.
Ich

1
Funktioniert und motiviert auch dazu, Klassen anstelle von Strukturen zu verwenden. Youtube.com/watch?v=_V2sBURgUBI
Isaac Carol Weisberg

Das ist ein super Tipp !!
Peymankh

5
Ab Xcode 11 können Sie Generate Memberwise Initializer auch für Strukturen verwenden!
Brock Batsell

Fantastisch!!! Es ist nicht die richtige Antwort, aber ein sehr guter Tipp! Hat mir viel geholfen!
GuiOS


1

Wir haben jetzt ein Rubin-Juwel, um eine vollständige schnelle Datenmodelldatei zeilenweise zu analysieren und Modifikatoren für den öffentlichen Zugriff, Standardinitialisierer für öffentliche Mitglieder und andere Dinge in einer separaten, automatisch generierten, schnellen Ausgabe-Datei hinzuzufügen.

Dieses Juwel heißt swift_republic

Bitte lesen Sie die folgende Dokumentation, um dieses Juwel auszuführen:

https://github.com/mehul90/swift_republic


1
Tolle Lösung !! Ich habe bereits einen Wrapper für erstellt swift_republicund funktioniert einwandfrei.
Md Shahed Hossain
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.