Mit Xcode 6.3 wurden neue Anmerkungen eingeführt, um die Absicht von APIs in Objective-C besser auszudrücken (und natürlich um eine bessere Swift-Unterstützung zu gewährleisten). Diese Anmerkungen waren natürlich nonnull
, nullable
und null_unspecified
.
Bei Xcode 7 werden jedoch viele Warnungen angezeigt, z.
Dem Zeiger fehlt ein Nullfähigkeitstyp-Bezeichner (_Nonnull, _Nullable oder _Null_unspecified).
Darüber hinaus verwendet Apple einen anderen Typ von Nullabilitätsspezifizierern, die ihren C-Code ( Quelle ) markieren :
CFArrayRef __nonnull CFArrayCreate(
CFAllocatorRef __nullable allocator, const void * __nonnull * __nullable values, CFIndex numValues, const CFArrayCallBacks * __nullable callBacks);
Zusammenfassend haben wir nun diese 3 verschiedenen Annotationen zur Nullbarkeit:
nonnull
,nullable
,null_unspecified
_Nonnull
,_Nullable
,_Null_unspecified
__nonnull
,__nullable
,__null_unspecified
Obwohl ich weiß, warum und wo ich welche Annotation verwenden soll, bin ich etwas verwirrt darüber, welche Art von Annotationen ich wo und warum verwenden soll. Folgendes könnte ich sammeln:
- Für Eigenschaften sollte ich verwenden
nonnull
,nullable
,null_unspecified
. - Für Methodenparameter sollte ich
nonnull
,nullable
,null_unspecified
. - Für C Methoden , die ich verwenden sollte
__nonnull
,__nullable
,__null_unspecified
. - In anderen Fällen, wie zum Beispiel Doppelzeiger soll ich verwenden
_Nonnull
,_Nullable
,_Null_unspecified
.
Aber ich bin immer noch verwirrt darüber, warum wir so viele Anmerkungen haben, die im Grunde das Gleiche tun.
Meine Frage lautet also:
Was ist der genaue Unterschied zwischen diesen Anmerkungen, wie werden sie richtig platziert und warum?
quelle
Antworten:
Aus der
clang
Dokumentation :, und
Also für Methode zurückgibt und Parameter , die Sie die die Doppelunterstrichene Möglichkeiten nutzen
__nonnull
/__nullable
/__null_unspecified
statt entweder die Einzelunterstrichene diejenigen, oder anstelle der nicht-unterstrichene diejenigen. Der Unterschied besteht darin, dass die einfach und doppelt unterstrichenen nach der Typdefinition platziert werden müssen, während die nicht unterstrichenen vor der Typdefinition stehen müssen.Somit sind die folgenden Erklärungen gleichwertig und richtig:
Für Parameter:
Für Eigenschaften:
Die Dinge werden jedoch komplizierter, wenn es sich um Doppelzeiger oder Blöcke handelt, die etwas anderes als void zurückgeben, da die nicht unterstrichenen hier nicht zulässig sind:
Ähnlich wie bei Methoden, die Blöcke als Parameter akzeptieren, beachten Sie bitte, dass das Qualifikationsmerkmal
nonnull
/nullable
für den Block und nicht für seinen Rückgabetyp gilt. Daher sind die folgenden äquivalent:Wenn der Block einen Rückgabewert hat, werden Sie in eine der Unterstrichversionen gezwungen:
Als Fazit können Sie beide verwenden, solange der Compiler das Element bestimmen kann, dem das Qualifikationsmerkmal zugewiesen werden soll.
quelle
_Null_unspecified
in Swift bedeutet dies optional? nicht optional oder was?Aus dem Swift-Blog :
quelle
Dieser Artikel hat mir sehr gut gefallen , daher zeige ich nur, was der Autor geschrieben hat: https://swiftunboxed.com/interop/objc-nullability-annotations/
null_unspecified:
Brücken zu einem implizit entpackten Swift optional. Dies ist die Standardeinstellung .nonnull
: der Wert wird nicht Null sein; Brücken zu einer regelmäßigen Referenz.nullable
: der Wert kann Null sein; Brücken zu einem optionalen.null_resettable
: Der Wert kann beim Lesen niemals Null sein, aber Sie können ihn auf Null setzen, um ihn zurückzusetzen. Gilt nur für Eigenschaften.Die obigen Notationen unterscheiden sich dann, ob Sie sie im Kontext von Eigenschaften oder Funktionen / Variablen verwenden:
Der Autor des Artikels lieferte auch ein schönes Beispiel:
quelle
Sehr praktisch ist
und schließen mit
Dies macht die Notwendigkeit der Codeebene 'nullibis' zunichte :-), da es sinnvoll ist anzunehmen, dass alles nicht null (oder
nonnull
oder_nonnull
oder__nonnull
) ist, sofern nicht anders angegeben.Leider gibt es auch hier Ausnahmen ...
typedef
s werden nicht angenommen__nonnull
(beachten Sie,nonnull
scheint nicht zu funktionieren, muss es hässlichen Halbbruder verwenden)id *
braucht ein explizites Nullibi, aber wow die Sündensteuer (_Nullable id * _Nonnull
<- rate mal was das bedeutet ...)NSError **
wird immer als nullbar angenommenSo mit den Ausnahmen von den Ausnahmen und die inkonsistenten Schlüsselwörter die gleiche Funktionalität entlocken, vielleicht der Ansatz ist es, die hässlichen Versionen verwenden
__nonnull
/__nullable
/__null_unspecified
und Swap , wenn die complier ... beschwert? Vielleicht existieren sie deshalb in den Apple-Headern?Interessanterweise hat es etwas in meinen Code eingefügt ... Ich verabscheue Unterstriche im Code (Apple C ++ - Typ der alten Schule), daher bin ich mir absolut sicher, dass ich diese nicht eingegeben habe, aber sie erschienen sind (ein Beispiel von mehreren):
Und noch interessanter ist, wo das __nullable eingefügt wurde, ist falsch ... (eek @!)
Ich wünschte wirklich, ich könnte nur die Nicht-Unterstrich-Version verwenden, aber anscheinend funktioniert das nicht mit dem Compiler, da dies als Fehler gekennzeichnet ist:
quelle