如果在模拟器中运行较新的iPhone,则didBeginContact中会出现快速错误 [英] swift error in didBeginContact if running newer iPhone in simulator

查看:63
本文介绍了如果在模拟器中运行较新的iPhone,则didBeginContact中会出现快速错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是"didBeginContact"方法中的代码:

this is the Code in the "didBeginContact" method:

        if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask
    {

        if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000003"{

            contact.bodyB.node!.removeFromParent()
        }
        if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000004"{

            contact.bodyB.node!.removeFromParent()
        }

    }

    else

    {
        if contact.bodyB.node!.name == "0" && contact.bodyA.node!.name == "1000003"{

            contact.bodyA.node!.removeFromParent()
        }
        if contact.bodyB.node!.name == "0" && contact.bodyA.node!.name == "1000004"{

            contact.bodyA.node!.removeFromParent()
        }
    }

它可以在"iPhone 4s"和"iPhone 5"模拟中运行,并在更高版本中失败,并显示以下错误消息:

it works in "iPhone 4s" and "iPhone 5" simulation and fail in a higher version with this error message:

致命错误:解开可选值时意外发现nil(lldb)"

"fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)"

这是标记为红色的行:

if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000004"{

很高兴知道:名称为"1000004"的对象是我在"GameScene"类中创建的SKSpriteNode: let TestPixel = SKSpriteNode(imageNamed:"6")

nice to know: the object with the name "1000004" is a SKSpriteNode I create in the "GameScene" class: let TestPixel = SKSpriteNode(imageNamed: "6")

该对象的属性在"touchesBegan"方法中.这是该代码:

the property for this object are in the "touchesBegan" method. here is the code for that:

            TestPixel.name = "1000004"
            TestPixel.anchorPoint = CGPointMake(0.5, 0.5)
            TestPixel.userInteractionEnabled = false
            TestPixel.zPosition = 1000003
            TestPixel.size = CGSizeMake(1, 1)
            TestPixel.position = CGPointMake(positionInScene.x, positionInScene.y)
            TestPixel.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "6"), size: TestPixel.size)
            TestPixel.physicsBody?.categoryBitMask = ClickOnCategory
            TestPixel.physicsBody?.contactTestBitMask = BuildingsCategory
            TestPixel.physicsBody?.affectedByGravity = false
            TestPixel.physicsBody?.dynamic = true
            TestPixel.physicsBody?.collisionBitMask = 0
            addChild(TestPixel)

如果此SpriteNode(name:"1000004")击中了我在"didMoveToView"方法中创建的另一个SpriteNode,则会发生错误,这是代码:

the error occur if this SpriteNode(name:"1000004") hit another SpriteNode which I create in the "didMoveToView" method, here is the code:

func addBG(){

        let background = SKSpriteNode(imageNamed: "0")
        background.name = "0"
        background.anchorPoint = CGPointMake(0.5, 0.5)
        background.zPosition = 1
        background.position = CGPointMake(CGRectGetMinX(self.frame)+self.frame.width/4,CGRectGetMaxY(self.frame)-self.frame.height/4)
        background.physicsBody = SKPhysicsBody(texture: SKTexture(imageNamed: "0"), size: background.size)
        background.physicsBody?.categoryBitMask = BuildingsCategory
        background.physicsBody?.affectedByGravity = false
        background.physicsBody?.dynamic = true
        background.physicsBody?.collisionBitMask = 0
        self.addChild(background)

    }

    addBG()

,并且在"didMoveToView"中也是:

and in the "didMoveToView" also is:

physicsWorld.contactDelegate = self

"GameScene"类中的categoryBitMask设置如下:

the categoryBitMask in the "GameScene" class is set like this:

class GameScene: SKScene, SKPhysicsContactDelegate{

let BuildingsCategory  : UInt32 = 0x1 << 1
let ClickOnCategory : UInt32 = 0x1 << 2

是的,正如我所说的,它可以在"iPhone 4s"和"iPhone 4s"模拟器中使用"iPhone 5"但不是更高版本...为什么有任何想法?谢谢

yeah ok as I said it works in simulator with "iPhone 4s" && "iPhone 5" but not in higher versions... any ideas why? thanks

推荐答案

是的,我可以告诉你原因:

Yes, I can tell you why:

if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000003"{
    contact.bodyB.node!.removeFromParent() <----PROBLEM
}
if contact.bodyA.node!.name == "0" && contact.bodyB.node!.name == "1000004"{
    contact.bodyB.node!.removeFromParent()
}

发生了什么事,是您在执行第一个if语句,该语句从父级中删除了,然后您尝试在之后再次访问它.好吧,如果您从父级删除,那么该节点在内存中的维护是什么?可能什么也没有,所以在第一行,它使节点无效.然后,您的代码将继续进入另一个if条件,并且您现在正尝试解开nil.您可以在此处使用 ELSE IF 而不是if

What is happening, is you are hitting your 1st if statement, which does the remove from parent, then you are trying to access it again after. Well if you remove from parent, what is maintaining the node in memory? Probably nothing, so at that first line, it nils out the node. Your code then continues into another if condition, and you are now trying to unwrap a nil. This is where you would use ELSE IF instead of if.

我强烈建议您使用Sprite Kit做些其他事情,那就是在接触阶段从不删除节点.您可能发生了多个联系,并且可能需要处理所有这些联系情况,因此最好使节点保持活动状态.

Something else I strongly recommend doing with sprite kit is to never remove nodes during the contact phase. You could have multiple contacts happening, and you may need to handle all of these contact situations, so it is best to keep the node alive.

相反,无论何时要删除节点,都将它们放入队列(数组或集合)中,然后在didFinishUpdate方法上循环遍历队列并删除所有节点.

Instead, whenever you want to remove nodes, place them into a queue (array or set), then on your didFinishUpdate method, loop through the queue and remove all the nodes.

我做的另一个技巧是,我在categoryBitMask上保留了第31位,以确定一个子画面是否存在还是死了,然后在didContact方法上,对其进行防范.

Another trick I do, is I reserve bit 31 on the categoryBitMask to determine if a sprite is alive or dead, then on the didContact methods, I place a guard against it.

E.G.

func didBeginContact(contact: SKPhysicsContact!)
{
    guard let bodies = (a:contact.bodyA,b:contact.bodyB) where a.categoryBitMask < 1 << 31 && b.categoryBitMask < 1 << 31
    else
    {
        return
    }
    // do other work here
}

Seift 3.0

Seift 3.0

func didBeginContact(contact: SKPhysicsContact!)
{
    guard let bodies = (a:contact.bodyA,b:contact.bodyB, a.categoryBitMask < 1 << 31 && b.categoryBitMask < 1 << 31
    else
    {
        return
    }
    // do other work here
}

这篇关于如果在模拟器中运行较新的iPhone,则didBeginContact中会出现快速错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆