web-dev-qa-db-fra.com

Comment créer un tableau d'objets de taille fixe

Dans Swift, j'essaie de créer un tableau de 64 SKSpriteNode. Je veux d'abord l'initialiser vide, puis je mettrais les Sprites dans les 16 premières cellules et dans les 16 dernières cellules (simulant un jeu d'échecs).

D'après ce que j'ai compris dans le document, j'attendrais quelque chose comme:

var sprites = SKSpriteNode()[64];

ou

var sprites4 : SKSpriteNode[64];

Mais ça ne marche pas. Dans le second cas, une erreur s’affiche: "Les tableaux de longueur fixe ne sont pas encore pris en charge". Cela peut-il être réel? Pour moi, cela ressemble à une fonctionnalité de base. Je dois accéder à l'élément directement par leur index.

84
Henri Lapierre

Les tableaux de longueur fixe ne sont pas encore pris en charge. Qu'est-ce que cela signifie réellement? Non pas que vous ne puissiez pas créer un tableau de n beaucoup de choses - vous pouvez évidemment faire let a = [ 1, 2, 3 ] pour obtenir un tableau de trois Ints. Cela signifie simplement que la taille d'un tableau n'est pas quelque chose que vous pouvez déclarer en tant qu'information de type.

Si vous voulez un tableau de nils, vous aurez d'abord besoin d'un tableau de type facultatif - [SKSpriteNode?], pas [SKSpriteNode] - si vous déclarez une variable de type non facultatif, que ce soit un tableau ou une valeur unique, il ne peut s'agir de nil. (Notez également que [SKSpriteNode?] est différent de [SKSpriteNode]?... vous voulez un tableau d'options et non un tableau facultatif.)

Swift est très explicite par sa conception pour exiger l’initialisation des variables, car les hypothèses sur le contenu des références non initialisées sont l’un des moyens par lesquels les programmes en C (et quelques autres langages) peuvent devenir bogués. Donc, vous devez explicitement demander un tableau [SKSpriteNode?] contenant 64 nils:

var sprites = [SKSpriteNode?](repeating: nil, count: 64)

Cela retourne en fait un [SKSpriteNode?]?, cependant: un tableau facultatif de sprites facultatifs. (Un peu étrange, car init(count:,repeatedValue:) ne devrait pas pouvoir renvoyer nil.) Pour utiliser le tableau, vous devez le décompresser. Il y a plusieurs façons de le faire, mais dans ce cas, je privilégierais la syntaxe de liaison facultative:

if var sprites = [SKSpriteNode?](repeating: nil, count: 64){
    sprites[0] = pawnSprite
}
129
rickster

Le mieux que vous puissiez faire pour le moment est de créer un tableau avec un nombre initial répétant nil:

var sprites = [SKSpriteNode?](count: 64, repeatedValue: nil)

Vous pouvez ensuite renseigner les valeurs de votre choix.


Dans Swift 3.:

var sprites = [SKSpriteNode?](repeating: nil, count: 64)
57
drewag

Pour l'instant, l'un des plus proches serait un Tuple avec un nombre fixe d'éléments.

typealias buffer = (
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode,
    SKSpriteNode, SKSpriteNode, SKSpriteNode, SKSpriteNode)

Mais c’est (1) très inconfortable à utiliser et (2) la structure de la mémoire n’est pas définie. (du moins inconnu pour moi)

5
Eonil

Cette question a déjà été répondue, mais pour quelques informations supplémentaires au moment de Swift 4:

En cas de performances, vous devez réserver de la mémoire pour le tableau, en cas de création dynamique, tel que l'ajout d'éléments avec Array.append().

var array = [SKSpriteNode]()
array.reserveCapacity(64)

for _ in 0..<64 {
    array.append(SKSpriteNode())
}

Si vous connaissez la quantité minimale d'éléments que vous allez ajouter, mais pas la quantité maximale, vous devriez plutôt utiliser array.reserveCapacity(minimumCapacity: 64).

4
Andreas

Déclarez un SKSpriteNode vide afin qu'il ne soit plus nécessaire de le décompresser

var sprites = [SKSpriteNode](count: 64, repeatedValue: SKSpriteNode())
4
Carlos.V

Swift 4

Vous pouvez en quelque sorte la considérer comme un tableau d'objet par opposition à un tableau de références.

  • [SKSpriteNode] doit contenir des objets réels
  • [SKSpriteNode?] peut contenir des références à des objets ou nil

Exemples

  1. Créer un tableau avec 64 défaut SKSpriteNode:

    var sprites = [SKSpriteNode](repeatElement(SKSpriteNode(texture: nil),
                                               count: 64))
    
  2. Créer un tableau avec 64 emplacements vides (a.k.a optionnels ):

    var optionalSprites = [SKSpriteNode?](repeatElement(nil,
                                          count: 64))
    
  3. Conversion d’un tableau d’options en tableau d’objets (réduction de [SKSpriteNode?] en [SKSpriteNode]):

    let flatSprites = optionalSprites.flatMap { $0 }
    

    La count de la flatSprites résultante dépend du nombre d'objets dans optionalSprites: les options vides seront ignorées, c'est-à-dire ignorées.

4
SwiftArchitect