Cet article est l'article du 12ème jour du Swift Advent Calendar 2014.
Le calendrier de l'Avent approche à grands pas. Décembre est déjà le 12, ce qui vous fait sentir la fin de l'année.
Personnellement, en vieillissant, je sens que l'année est très tôt. L'ancêtre a également laissé les mots ** «Le nombre de jours vécus dans une année est le contraire de l'âge» **. (Ne faisons pas d'erreur que la valeur ne change pas tellement même si le nombre inverse de 1 ou plus est pris)
Passons maintenant au sujet de Swift.
La conception du langage pour Swift est bonne, mais la prise en charge de Xcode et du compilateur est toujours si élevée que je n'ai pas été motivé pour créer une application par moi-même. (Si vous optimisez un certain code, il peut boucler indéfiniment)
Cette fois, il ne s'agit pas du compilateur, mais d'accéder directement à la mémoire à l'aide de pointeurs.
Tout d'abord, Swift dispose d'une API compatible avec le langage C.
Par exemple, lors de la création d'une application iOS ou Mac
var error: NSError? = nil
if !_fetchedResultsController!.performFetch(&error) {
println("Unresolved error \(error), \(error?.localizedDescription)")
}
return _fetchedResultsController!
Vous devriez vous souvenir d'avoir écrit. (Situé dans le modèle CoreData du projet)
L'adresse de la variable déclarée dans ce NSError?
Est passée à l'argument de performFetch
.
Si vous allez voir la définition de performFetch
func performFetch(error: NSErrorPointer) -> Bool
Et NSErrorPointer
est aliasé comme ci-dessous.
typealias NSErrorPointer = AutoreleasingUnsafeMutablePointer<NSError?>
Le ʻAutoreleasingUnsafeMutablePointer
Par nature, Swift n'a pas d'accès direct à la mémoire.
Cependant, c'est possible en utilisant ʻUnsafePointer
J'ai mentionné ʻUnsafe Pointer
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> |
Comme mentionné ci-dessus, les types de pointeurs sont
Il est divisé en.
comme une fonctionnalité
--Swift utilise nil
pour représenter NULL
en langage C
--Converti en ʻUnsafePointer
Utilisons-les réellement.
Cette fois, à titre d'exemple de pointeur, nous allons créer une fonction swapByPointer et l'introduire. (La fonction d'échange apparaît fréquemment dans l'exemple du pointeur.)
Je veux que le type soit de n'importe quel type, donc j'utilise des génériques.
** fonction swapByPointer **
func swapByPointer<T>(x: UnsafeMutablePointer<T>, y: UnsafeMutablePointer<T>) {
let z: T = x.memory
x.memory = y.memory
y.memory = z
}
appel
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)")
Ça ressemble à ça.
Nous définissons une fonction de swap normale et passons l'adresse comme argument. Nous affectons directement à la mémoire pointée par l'adresse dans la fonction.
Je pense qu'il y a un tsukkomi de "Non, n'est-il pas plus simple d'utiliser un tel ʻinout`?"
Cette fois, je veux utiliser ** pointer ** explicitement, donc je n'utilise pas ʻinout`.
Si vous demandez "Qu'est-ce que ʻinout`?", Veuillez lire le code ci-dessous.
** fonction swapByInout (version inout) **
func swapByInout<T>(inout x: T, inout y: T) {
let z: T = x
x = y
y = z
}
appel
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)")
La référence précédente provenait de l'adresse de la variable déjà réservée, mais si vous êtes familier avec le langage C, ce sera "** memory alloc **!?".
Bien sûr, il y en a.
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)
En guise de commentaire, j'ai également noté la situation en langage C.
Il y a trois codes qui nécessitent une explication: ʻalloc,
dealloc et
memory`.
var p = UnsafeMutablePointer
En langage C
Type *p = (Type *)malloc(num * sizeof(Type));
// or
Type *p = (Type *)calloc(num, sizeof(Type));
Ce sera.
Spécifiez le nombre de types déclarés dans num
pour garantir la taille de mémoire requise.
p.dealloc(num)
En langage C
free(p);
Je le publie.
p.memory
En langage C
*p
est. Utilisé pour faire référence à la valeur de l'adresse.
Généralement, si vous connaissez ce degré, vous pouvez construire Swift avec l'idée du langage C.
J'ai donné ce code à Gist, alors veuillez vous y référer si vous le souhaitez.
https://gist.github.com/kaneshin/564fc0780e0d1c9cac7d
De plus, si vous parlez de pointeurs, vous devriez vous demander ** "Qu'est-ce qu'un pointeur de fonction?" **.
Bien sûr, il existe également une API compatible pour travailler avec des pointeurs de fonction. Disons que quelqu'un veut le savoir ou l'introduira lorsque le ** numéro de stock de cet article atteint environ 100 **.
C'était une si bonne affaire pour quiconque, mais je ne pense pas qu'il y ait un article en japonais traitant des pointeurs dans Swift, alors veuillez le toucher si vous le souhaitez.