Strukturen, die in Swift 3 aufeinander verweisen

8

Ich habe zwei CoreData-Entitäten mit einer Eins-zu-Eins-Beziehung. Ich möchte Strukturen basierend auf diesen Entitäten erstellen. Mein Code:

%Vor%

Aber ich habe einen Fehler: Value type 'DetailedPin' cannot have a stored property that references itself . Und der gleiche Fehler für Pin struct. Wie kann ich mit diesem Problem umgehen? Danke.

    
RomanHouse 23.11.2016, 18:22
quelle

4 Antworten

18

Das Problem ist, dass ein Optional seinen Wrapped -Wert inline speichert (siehe Mike Ashs fantastischer Blog-Beitrag für weitere Informationen zu diesem Thema - was bedeutet, dass eine Optional -Instanz (egal ob nil oder nicht) mindestens belegen wird die gleiche Menge an Speicher wie der Typ, den Sie in seiner .some -Fall speichern möchten (der Wrapped -Typ).

Da Ihre Pin struct eine Eigenschaft vom Typ DetailedPin? hat und DetailedPin eine Eigenschaft vom Typ Pin? hat, wäre unendlicher Speicher erforderlich, um diese Werte inline zu speichern.

Die Lösung besteht also einfach darin, eine indirekte Ebene hinzuzufügen. Eine Möglichkeit wäre, Pin und / oder DetailedPin als Referenztyp (dh class ) als @ dfri hat vorgeschlagen .

Wenn Sie jedoch die Wertesemantik von Pin und DetailedPin beibehalten möchten, besteht eine Option darin, einen Wrappertyp zu erstellen, der von einer Klasseninstanz unterstützt wird, um die erforderliche Indirektion bereitzustellen:

%Vor%

Sie können jetzt einfach den Indirect -Wrapper für eine (oder beide) Ihrer structs-Eigenschaften verwenden:

%Vor%     
Hamish 24.11.2016, 01:18
quelle
4

Eine Eins-zu-eins-Beziehung zwischen zwei Entitäten ist nur gültig, wenn mindestens eine der Verbindungen zwischen diesen Entitäten vom -Referenz -Typ ist; Für zwei reine Werttypen wird ihre Eins-zu-Eins-Beziehung rekursiv.

Angenommen, Sie erstellen ein Objekt vom Werttyp DetailedPin . Es enthält eine Instanzeigenschaft ( pin ) des Werttyps Pin , was bedeutet, dass diese Instanzeigenschaft Teil des Werts ist, der die Instanz von DetailedPin ist. Die Instanzeigenschaft pin von und die Instanz von DetailedPin hat nun den Wert Pin , der selbst eine Instanzeigenschaft ( detailedPin ) vom Werttyp DetailedPin enthält. Dieses Instanzmitglied detailedPin ist wiederum _ein Teil des Wertes, der die Instanz pin ) ist, aber wiederum besitzt detailedPin selbst einen Wert vom Typ pin , und so wird der rekursive Tanz fortgesetzt ...

Sie können dies umgehen, indem Sie eine Ihrer Strukturen in einen Referenztyp verwandeln ( class ):

%Vor%

Beachten Sie, dass die rekursive Beziehung, die oben behandelt wird, nicht direkt mit ARC (automatische Referenzzählung) oder starken Referenzzyklen zusammenhängt, sondern dass der Wert einer Werttypinstanz die Instanz selbst und der Wert aller darin enthaltenen Werttyp- (Teil-) Eigenschaften (sowie die Referenz auf alle darin enthaltenen Referenztyp- (Teil-) Eigenschaften).

Seien Sie vorsichtig, wenn Sie beide Eins-zu-Eins-Entitäten als Referenztypen definieren: In diesem Fall müssen Sie sicherstellen, dass eine der Referenzen zwischen den beiden Typen weak ist. Zum Beispiel:

%Vor%

Falls Sie weak oben nicht angeben (d. h., dass sich beide durch die standardmäßigen starken Referenzen gegenseitig ansprechen), haben Sie einen starken Referenzzyklus zwischen den beiden aufeinander bezogenen Instanzen

%Vor%     
dfri 23.11.2016 19:29
quelle
2

Dies sollte erreichen, was Sie brauchen:

%Vor%

Verwendung:

%Vor%     
Josh Sklar 26.01.2018 20:35
quelle
1

Wie hier erwähnt: indirekte enums und structs , könnte eine elegante Lösung sein, Ihre Referenz innerhalb einer Enum mit einem indirect case.

In Ihrem Beispiel würde dies Folgendes ergeben:

%Vor%

oder direkt, je nach Ihren Bedürfnissen:

%Vor%

Jenseits meines Verständnisses sagt indirect dem Compiler, dass es eine Rekursion in Ihrer Enumeration gibt, und es sollte die notwendige Indirektionsebene einfügen .

    
Martin 30.06.2017 09:18
quelle

Tags und Links