Dieser Artikel ist der Artikel zum 12. Tag von Swift Advent Calendar 2014.
Der Adventskalender ist gleich um die Ecke. Der Dezember ist bereits der 12., wodurch Sie das Ende des Jahres spüren.
Persönlich habe ich mit zunehmendem Alter das Gefühl, dass das Jahr sehr früh ist. Der Vorfahr hinterließ auch die Worte ** "Die Anzahl der Tage in einem Jahr ist das Gegenteil des Alters" **. (Machen wir keinen Fehler, dass sich der Wert nicht so stark ändert, selbst wenn die inverse Zahl 1 oder mehr verwendet wird.)
Kommen wir nun zum Thema Swift.
Das Sprachdesign für Swift ist gut, aber die Unterstützung für Xcode und den Compiler ist immer noch so hoch, dass ich nie motiviert war, selbst eine App zu erstellen. (Wenn Sie einen bestimmten Code optimieren, kann es zu einer Endlosschleife kommen.)
Diesmal geht es nicht um den Compiler, sondern darum, mit Zeigern direkt auf den Speicher zuzugreifen.
Erstens hat Swift eine API, die mit der C-Sprache kompatibel ist.
Zum Beispiel beim Erstellen einer iOS- oder Mac-Anwendung
var error: NSError? = nil
if !_fetchedResultsController!.performFetch(&error) {
println("Unresolved error \(error), \(error?.localizedDescription)")
}
return _fetchedResultsController!
Sie sollten sich daran erinnern, geschrieben zu haben. (Befindet sich in der CoreData-Vorlage des Projekts)
Die Adresse der in diesem NSError deklarierten Variablen wird an das Argument performFetch übergeben.
Wenn Sie die Definition von "performFetch" sehen
func performFetch(error: NSErrorPointer) -> Bool
Und NSErrorPointer
ist wie folgt aliasiert.
typealias NSErrorPointer = AutoreleasingUnsafeMutablePointer<NSError?>
Der AutoreleasingUnsafeMutablePointer
UnsafePointer <T>
usw.Swift hat von Natur aus keinen direkten Zugriff auf den Speicher.
Es ist jedoch möglich, "UnsafePointer
Ich habe UnsafePointer <T>
** etc. ** von früher erwähnt, aber es gibt andere Typen in der offiziellen Referenz.
For return types, variables, and arguments, the following mappings apply:
C Syntax | Swift Syntax |
---|---|
const Type * |
UnsafePointer<Type> |
Type * |
UnsafeMutablePointer<Type> |
For class types, the following mappings apply:
C Syntax | Swift Syntax |
---|---|
Type * const * |
UnsafePointer<Type> |
Type * __strong * |
UnsafeMutablePointer<Type> |
Type ** |
AutoreleasingUnsafeMutablePointer<Type> |
Wie oben erwähnt, sind die Arten von Zeigern
Es ist unterteilt in.
als Merkmal
--Swift verwendet "nil", um "NULL" in C-Sprache darzustellen
Lassen Sie uns diese tatsächlich verwenden.
Dieses Mal werde ich als Beispiel für einen Zeiger eine swapByPointer-Funktion einführen. (Die Swap-Funktion wird im Zeigerbeispiel häufig angezeigt.)
Ich möchte, dass der Typ ein beliebiger Typ ist, daher verwende ich Generika.
** swapByPointer Funktion **
func swapByPointer<T>(x: UnsafeMutablePointer<T>, y: UnsafeMutablePointer<T>) {
let z: T = x.memory
x.memory = y.memory
y.memory = z
}
Anruf
var a: Int = 10
var b: Int = 20
// a = 10, b = 20
println("a = \(a), b = \(b)")
// Swap
swapByPointer(&a, &b)
// a = 20, b = 10
println("a = \(a), b = \(b)")
Es sieht aus wie das.
Ich habe eine normale Swap-Funktion definiert und die Adresse als Argument übergeben. Der Speicher, auf den die Adresse zeigt, wird direkt in der Funktion zugewiesen.
Ich denke, es gibt einen Tsukkomi, der sagt: "Nein, ist es nicht einfacher, solch ein" Inout "zu verwenden?"
Dieses Mal möchte ich ** Zeiger ** explizit verwenden, daher verwende ich nicht inout
.
Wenn Sie fragen "Was ist" inout "?", Lesen Sie bitte den folgenden Code.
** swapByInout-Funktion (Inout-Version) **
func swapByInout<T>(inout x: T, inout y: T) {
let z: T = x
x = y
y = z
}
Anruf
var a: Int = 10
var b: Int = 20
// a = 10, b = 20
println("a = \(a), b = \(b)")
// Swap
swapByInout(&a, &b)
// a = 20, b = 10
println("a = \(a), b = \(b)")
Die vorherige Referenz stammt von der Adresse der bereits reservierten Variablen. Wenn Sie jedoch mit der Sprache C vertraut sind, lautet sie "** Speicherzuweisung ** !?".
Natürlich gibt es.
alloc
// Use UnsafeMutablePointer<T>
typealias IntPointer = UnsafeMutablePointer<Int>
// C Language:
// typedef int *IntPointer;
var a_ptr = IntPointer.alloc(1)
// C Language:
// int *a_ptr = (int *)malloc(1 * sizeof(int));
// IntPointer a_ptr = (IntPointer)malloc(1 * sizeof(int));
// or
// int *a_ptr = (int *)calloc(1, sizeof(int));
var b_ptr = IntPointer.alloc(1)
a_ptr.memory = a
// C Language:
// *a_ptr = a;
b_ptr.memory = b
// a_ptr.memory = 10, b_ptr.memory = 20
println("a_ptr.memory = \(a_ptr.memory), b_ptr.memory = \(b_ptr.memory)")
// Swap
swapByPointer(a_ptr, b_ptr)
// a_ptr.memory = 20, b_ptr.memory = 10
println("a_ptr.memory = \(a_ptr.memory), b_ptr.memory = \(b_ptr.memory)")
// Destroy
a_ptr.dealloc(1)
// C Language:
// free(a_ptr);
b_ptr.dealloc(1)
Als Kommentar habe ich auch die Situation in C-Sprache niedergeschrieben.
Es gibt drei Codes, die einer Erklärung bedürfen: "alloc", "dealloc" und "memory".
var p = UnsafeMutablePointer
In C-Sprache
Type *p = (Type *)malloc(num * sizeof(Type));
// or
Type *p = (Type *)calloc(num, sizeof(Type));
Es wird sein.
Geben Sie die Anzahl der deklarierten Typen in "num" an, um die erforderliche Speichergröße zu sichern.
p.dealloc(num)
In C-Sprache
free(p);
Ich gebe es frei.
p.memory
In C-Sprache
*p
ist. Wird verwendet, um auf den Wert in der Adresse zu verweisen.
Wenn Sie diesen Abschluss kennen, können Sie Swift im Allgemeinen mit der Idee der C-Sprache erstellen.
Ich habe diesen Code an Gist weitergegeben. Bitte beziehen Sie sich darauf, wenn Sie möchten.
https://gist.github.com/kaneshin/564fc0780e0d1c9cac7d
Wenn Sie über Zeiger sprechen, sollten Sie auch gefragt werden ** "Was ist ein Funktionszeiger?" **.
Natürlich gibt es auch eine kompatible API für die Arbeit mit Funktionszeigern. Nehmen wir an, jemand möchte es wissen oder wird es vorstellen, wenn die ** Bestandsnummer dieses Artikels ungefähr 100 ** erreicht.
Es war so viel für jeden, aber ich glaube nicht, dass es einen Artikel auf Japanisch gibt, der sich mit Zeigern in Swift befasst. Bitte berühren Sie ihn, wenn Sie möchten.