web-dev-qa-db-ja.com

オブジェクトの固定サイズの配列を作成する方法

Swiftでは、64個のSKSpriteNodeの配列を作成しようとしています。最初に空に初期化してから、最初の16個のセルと最後の16個のセルにスプライトを配置します(チェスゲームをシミュレートします)。

私がドキュメントで理解したことから、私は次のようなものを期待していました:

var sprites = SKSpriteNode()[64];

または

var sprites4 : SKSpriteNode[64];

しかし、それは機能しません。 2番目の場合、「固定長配列はまだサポートされていません」というエラーが表示されます。それは本当ですか?基本的な機能のように思えます。インデックスによって要素に直接アクセスする必要があります。

83
Henri Lapierre

固定長配列はまだサポートされていません。それは実際にはどういう意味ですか? nの多くの配列を作成できないということではなく、明らかにlet a = [ 1, 2, 3 ]を実行して、3つのIntsの配列を取得できます。つまり、配列サイズは型情報としてと宣言できるものではないということです。

nilsの配列が必要な場合、最初にオプションの型の配列が必要になります— [SKSpriteNode?]ではなく[SKSpriteNode] —配列または単一の値であっても、非オプションの型の変数を宣言する場合、nilにはできません。 ([SKSpriteNode?][SKSpriteNode]?とは異なることにも注意してください...オプションの配列ではなく、オプションの配列が必要です。)

Swiftは、初期化されていない参照の内容に関する仮定がC(および他のいくつかの言語)のプログラムがバグになる可能性がある方法の1つであるため、変数の初期化を要求することについて非常に明示的です。したがって、64個のnilsを含む[SKSpriteNode?]配列を明示的に要求する必要があります。

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

これは実際には[SKSpriteNode?]?を返します:オプションのスプライトのオプションの配列。 (init(count:,repeatedValue:)はnilを返すことができないため、少し奇妙です。)配列を操作するには、それをアンラップする必要があります。これを行う方法はいくつかありますが、この場合、オプションのバインディング構文を使用します。

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

現時点でできる最善の方法は、初期カウントがnilである配列を作成することです。

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

その後、必要な値を入力できます。


Swift 3.で:

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

今のところ、意味的に最も近いものは、要素の数が固定されたタプルです。

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)

ただし、これは(1)使用するのが非常に不快であり、(2)メモリレイアウトが未定義です。 (少なくとも私には知られていない)

5
Eonil

空のSKSpriteNodeを宣言するので、アンラップする必要はありません

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

スイフト4

オブジェクトの配列と参照の配列と考えることができます。

  • [SKSpriteNode]には実際のオブジェクトが含まれている必要があります
  • [SKSpriteNode?]には、オブジェクトへの参照、またはnilを含めることができます

  1. 64defaultSKSpriteNodeを使用した配列の作成:

    var sprites = [SKSpriteNode](repeatElement(SKSpriteNode(texture: nil),
                                               count: 64))
    
  2. 64個の空のスロットを持つアレイの作成(別名optionals):

    var optionalSprites = [SKSpriteNode?](repeatElement(nil,
                                          count: 64))
    
  3. オプションの配列をオブジェクトの配列に変換する([SKSpriteNode?][SKSpriteNode]に折りたたみます):

    let flatSprites = optionalSprites.flatMap { $0 }
    

    結果のcountflatSpritesは、optionalSprites内のオブジェクトの数に依存します。空のオプションは無視されます。つまり、スキップされます。

4
SwiftArchitect

この質問はすでに回答されていますが、Swift 4の時点でいくつかの追加情報が必要です。

パフォーマンスの場合、配列を動的に作成する場合(Array.append()を使用して要素を追加するなど)、メモリを確保してください。

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

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

追加する要素の最小量はわかっているが、最大量はわかっていない場合は、array.reserveCapacity(minimumCapacity: 64)を使用する必要があります。

3
Andreas