用于假人的Swift SpriteKit ARC [英] Swift SpriteKit ARC for dummies

查看:63
本文介绍了用于假人的Swift SpriteKit ARC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力围绕强大的参考周期而奋斗。我一直在阅读来自苹果公司和某些网站上的文档,我觉得他们并没有真正解决我的问题。

I have been trying to wrap my head around strong reference cycles and I am struggling. I have been reading the documentation from apple and on some website and I feel like they dont really address my issues.

我了解您必须使用弱者和无主者,具体取决于对象可以为零。所以说你必须参加2个这样的课程

I understand you have to use weak and unowned depending if the object can be nil or not. So say you have to 2 classes like this

class Person {
   var dog: Dog?
  ....
}

class Dog {
  weak var person: Person?
}

互相引用我知道其中之一必须使用弱/无人。这是大多数教程中看到的经典示例。

that reference each other I know that one of them has to use weak/unowned. This is the classic example seen in most tutorials.

我也看到过这样的示例,它们对我也很有意义

I also have seen examples like this and they too make sense to me

class Person {

 unowned let gameScene: GameScene

 init(scene: GameScene) {
   self.gameScene = scene 
  ....
 }

我也了解NSTimers如果未失效,则可能导致较强的参考周期。我不使用NSTimers,所以这应该不是问题。

I also understand that NSTimers can cause strong reference cycles if not invalidated. I am not using NSTimers so this should not be a problem.

我进一步了解协议也可能导致内存泄漏,因此它们的处理方法是使其类协议

I furthermore understand that protocols can cause memory leaks too, so they way to handle them would be to make it a class protocol

protocol TestDelegate: class { }

,而在我试图引用该协议的地方,它会使其成为弱属性

and where I am trying to reference the protocol make it a weak property

 class: SomeClass {

  weak var myDelegate: TestDelegate?

 }

最后我知道关于闭包的地方,例如$

And finally I know about closures where I am capturing self like this

SKAction.runBlock { [unowned self] in
   self.player.runAction....
}

然而,当涉及到我的实际spritekit游戏时,我似乎遍地都有参考循环,即使是简单的课程,我也肯定不会引用其他课程,而且我也不明白为什么。

However when it comes to my actual spritekit game I seem to have reference cycles all over the place, even for simple classes I am sure dont reference another class, and I dont understand why.

所以我的主要问题是

1)所有属性都创建强引用循环还是仅创建在初始化类之前创建的全局属性?

1) Do all properties create strong reference cycles or only global properties that are created before a class is initialised?

2)还有哪些其他事情可能创建一个

2) What other things could potentially create a strong reference cycle in my simple classes?

例如我正在使用一个创建平台的类

For example I am using a class that creates platforms

class Platform: SKSpriteNode {

 /// basic code to create platforms 
 /// some simple methods to rotate platforms, move them left or right with SKActions.

现在我对陷阱,敌人等有类似的类。通常,它们通常只是设置精灵属性(物理物体等),并有一些方法对其进行动画处理或旋转。它们之间没有任何幻想,尤其是在引用其他类或场景方面。

Now I have similar classes like this for Traps, Enemies etc. Again they normally just set the sprite properties (physics body etc) and have some methods to animate them or rotate them. There is nothing fancy going on in them, especially in regards to referencing other classes or scenes.

在我的游戏场景中,我有一种创建平台的方法(对于敌人来说也是一样的) ,陷阱等)

In my gameScene I have a method to create platforms (would be same for enemies, traps etc)

func createPlatform() {

 let platform1 = Platform(.....
 platformNode.addChild(platform1)

 let platform2 = Platform(....
 platformNode.addChild(platform2)

 let platform3 = Platform(...
 platformNode.addChild(platform3)

 // platform node is just a SKNode in the gameScene to help maintain the difference zPositions of my objects.

}

在运行分配时,我可以看到3个平台中只有1个进入了过渡状态,当我切换到menuScene时,2保持不变。奇怪的是,总是只有1会被删除,无论我更改顺序还是创建/删除某些平台都没有关系,因此似乎它们创建了强大的引用,但1. S除外。 o如果我几次重播关卡,则可以快速在内存中拥有50-100个持久性平台。因此,我的场景也不会得到deinit,这会浪费更多的内存。

When I am running allocations I can see that only 1 of the 3 platforms goes into transient state, 2 stay persistent when I change to my menuScene. Whats strange is that always only 1 gets removed, doesnt matter if I change the order or create/delete some platforms. So it seems they are creating strong references, except 1. So if I replay my level a few times I can quickly have 50-100 persistant platforms in memory. My scene therefore also doesn't get deinit which is more memory wasted.

我还有另一个例子是

class Flag {
  let post: SKSpriteNode
  let flag: SKSpriteNode

  init(postImage: String, flagImage: String) {

       post = SKSpriteNode(imageNamed: postImage)
       ...


       flag = SKSpriteNode(imageNamed: flagImage)
       ...
       post.addChild(flag)
  }
}

同样的问题。我在场景中创建了一些标记,有时标记不会被删除,有时会被删除。再次,此类不引用任何场景或自定义类,它仅创建一个sprite并将其设置为动画。

and same problem. I create some flags in my scenes and sometimes a flag doesnt get removed, sometimes it does. Again this class does not reference any scene or custom class, it merely creates a sprite and animates it.

在我的场景中,我具有用于标志的全局属性

In my scene I have a global property for flag

 class GameScene: SKScene {

   var flag: Flag!

  func didMoveToView... 

 }

如果标志本身未引用GameScene,为什么会创建强引用?我也不能使用

Why would this create a strong reference if flag itself doesnt reference the GameScene?. Also I can't use

weak var flag: Flag!

因为一旦标志初始化,我就会崩溃。

because I get a crash once the flag gets initialised.

执行此操作时是否缺少某些明显的东西?
是否可以在Instruments中找到它们是一个好技巧,因为这对我来说似乎很疯狂。
这只是让我感到困惑,主要是因为我的类非常简单,并且不引用其他自定义类,场景,viewControllers等。

Is there something obvious I am missing when doing this? Is there a good trick to find them in Instruments because it seems madness for me. It just confusing to me mainly because my classes are quite simple and dont reference other custom classes, scenes, viewControllers etc.

推荐答案

感谢您提供所有答案,尤其是appzYourLift和您的详细答复。

Thank you for all the answers, especially appzYourLift and your detailed reply.

我整天都在研究spriteKit项目,还尝试了很多游乐场,我的游戏现在完全没有泄漏,没有强大的参考周期。

I was digging into my spriteKit project the whole day, also experimenting with playground a lot and my game is totally leak free now with no strong reference cycles to be found.

实际上,我发现很多泄漏/持久性类出现在工具中,只是因为其他东西没有解除分配。

It actually turned out a lot of the leaks/persistant classes I was seeing in instruments where simply there because something else didnt deallocate.

似乎永远的重复动作导致了我的泄漏。我要做的就是遍历场景中的所有节点并删除它们的动作。

Its seems that repeat action forever was causing my leaks. All I had to do is loop through all the nodes in my scene and remove their actions.

这个问题帮助了我

iOS 7 Sprite Kit释放内存

更新:我最近重新审视了此内容再次讨论该主题,因为我觉得不必手动删除节点上的操作,因为这样做会很麻烦。经过更多研究后,我发现了(我的)内存泄漏的确切问题。

UPDATE: I recently revisited this topic again because I felt like having to manually remove actions on nodes should not be necessary and could become cumbersome. After more research I found the precise issue for the (my) memory leaks.

像这样的 SKAction永远重复显然会导致泄漏。

Having a "SKAction repeat forever" like this apparently causes the leak.

let action1 = SKAction.wait(forDuration: 2)
let action2 = SKAction.run(someMethod) 
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence))

因此您需要将其更改为不引起泄漏

So you need to change it to this to not cause a leak

 let action1 = SKAction.wait(forDuration: 2)
 let action2 = SKAction.run { [weak self] in
     self?.someMethod()
 } 
 let sequence = SKAction.sequence([action1, action2])
 run(SKAction.repeatForever(sequence))

这直接来自Apple错误报告I

This is coming directly from an Apple bug report I made.

这篇关于用于假人的Swift SpriteKit ARC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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