Jan
Jan

Reputation: 2520

How can I conform to the Strideable protocol in Swift?

I'm trying to remove items from an array inside a For loop. In order to do that, I follow the recommendation here to loop backwards like this:

for (index, bullet:Bullet) in stride(from: bullets!.count - 1, through: 0, by: -1) {
    if(currentTime - bullet.life! > bullet.maxLife){
        bullet.removeFromParent()
        bullets?.removeAtIndex(index)
    }
}

But I'm getting an error

Type '($T12, Bullet)' does not conform to protocol 'Strideable'

UPDATE

Here is the class for the bullet. This is a Cocos2D app, hence the CCDrawNode Type.

import Foundation

  class Bullet: CCDrawNode {
  var speed:CGPoint?
  var maxSpeed:CGFloat?
  var angle:CGFloat?
  var life:CGFloat?
  var maxLife:CGFloat = 0.5

  init(angle: CGFloat){
    super.init()
    self.drawDot(ccp(0,0), radius: 2, color: CCColor.whiteColor());

    self.contentSize = CGSize(width: 4, height: 4)
    self.angle = angle
    maxSpeed = 10
    speed = CGPoint(x: maxSpeed! * CGFloat(sin(angle)), y: maxSpeed! * CGFloat(cos(angle)))

  }

  override func update(delta: CCTime) {
    self.position.x += speed!.x
    self.position.y += speed!.y
  }

}

Upvotes: 2

Views: 4676

Answers (3)

user887210
user887210

Reputation:

Here's a definition of the protocol: Stridable

You can implement it like this:

final class Foo: Strideable {
  var value: Int = 0
  init(_ newValue: Int) { value = newValue }
  func distanceTo(other: Foo) -> Int { return other.value - value }
  func advancedBy(n: Int) -> Self { return self.dynamicType(value + n) }
}

func ==(x: Foo, y: Foo) -> Bool { return x.value == y.value }
func <(x: Foo, y: Foo) -> Bool { return x.value < y.value }

let a = Foo(10)
let b = Foo(20)

for c in stride(from: a, to: b, by: 1) {
  println(c.value)
}

You need to provide the functions distanceTo, advancedBy and the operators == and <. There is more information about these functions in the documentation I linked.

Upvotes: 5

Martin R
Martin R

Reputation: 539975

Alternative solution using the filter() method, avoiding the need for an index altogether:

bullets!.filter { bullet -> Bool in
    if (currentTime - bullet.life! > bullet.maxLife) {
        bullet.removeFromParent()
        return false // remove from array
    } else {
        return true // keep in array
    }
}

Upvotes: 4

Antonio
Antonio

Reputation: 72770

You should change your loop as follows:

for index in stride(from: bullets!.count - 1, through: 0, by: -1) {
    let bullet = bullets![index]

by moving the bullet assignment to a separate statement inside the loop.

Upvotes: 0

Related Questions