I checked my old game and I want to update it in Swift 2.0. When I tried to fix it, Xcode found an error. Error is Value of type 'Set' has no member 'anyObject' on this line of code:
var touch:UITouch = touches.anyObject() as! UITouch
function:
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.runAction(SKAction.playSoundFileNamed("torpedo.mp3", waitForCompletion: false))
var touch:UITouch = touches.anyObject() as! UITouch //<-- Here is Error
var location:CGPoint = touch.locationInNode(self)
var torpedo:SKSpriteNode = SKSpriteNode(imageNamed: "torpedo")
torpedo.position = player.position
torpedo.physicsBody = SKPhysicsBody(circleOfRadius: torpedo.size.width/2)
torpedo.physicsBody!.dynamic = true
torpedo.physicsBody!.categoryBitMask = photonTorpedoCategory
torpedo.physicsBody!.contactTestBitMask = alienCategory
torpedo.physicsBody!.collisionBitMask = 0
torpedo.physicsBody!.usesPreciseCollisionDetection = true
var offset:CGPoint = vecSub(location, b: torpedo.position)
if (offset.y < 0){
return
self.addChild(torpedo)
var direction:CGPoint = vecNormalize(offset)
var shotLength:CGPoint = vecMult(direction, b: 1000)
var finalDestination:CGPoint = vecAdd(shotLength, b: torpedo.position)
let velocity = 568/1
let moveDuration:Float = Float(self.size.width) / Float(velocity)
var actionArray:NSMutableArray = NSMutableArray()
actionArray.addObject(SKAction.moveTo(finalDestination, duration: NSTimeInterval(moveDuration)))
actionArray.addObject(SKAction.removeFromParent())
torpedo.runAction(SKAction.sequence(actionArray))
}
So what to fix here ?
Given a Set
of UITouch
defined as follow
touches: Set<UITouch>
you can retrieve a touch with this code
let touch = touches.first
There is no need to force cast the retrieved element to UITouch
. Infact now the Apple APIs written in Objective-C have been updated with generics. This means that in this case you receive a Set
of UITouch
(not a Set
of NSObject
that could literally contains any object).
So the Set
already knows the contained elements are UITouch
.
The first
computed property does return an Optional
. Infact if the Set
is empty it does return nil
.
A good and safe technique to unwrap the element is
guard let touch = touches.first else {
debugPrint("Ops, no touch found...")
return
}
// here you can use touch