iOS 8 中的 SKSpriteNode 池似乎分配给了重叠的内存
Posted
技术标签:
【中文标题】iOS 8 中的 SKSpriteNode 池似乎分配给了重叠的内存【英文标题】:SKSpriteNode pools in iOS 8 seem to be allocated to overlapping memory 【发布时间】:2014-09-09 22:14:41 【问题描述】:我可能遗漏了什么。但是我当前在应用商店中的应用在 ios 7 中运行,但在 iOS 8 中完全失败,因为它不会创建预先分配的精灵池。除非精灵具有特别不同的属性,否则它们似乎被写入相同的地址。
在 iOS 7 中,以下代码生成一个包含 4 个唯一对象的集合。在 iOS 8 中,相同的代码生成一个只有 1 个对象的集合:
NSMutableSet *aSet = [NSMutableSet set];
SKColor *sameColor = [SKColor redColor];
CGSize sameSize = CGSizeMake(10, 10);
for (int i = 0; i < 4; i++)
//allocate a brand new sprite
SKSpriteNode *thisSprite1 = [[SKSpriteNode alloc] initWithColor:sameColor size:sameSize];
[aSet addObject:thisSprite1];
NSLog(@"aSet Count: %i", aSet.count);
iOS8 结果:
2014-09-09 15:06:43.065 MSM[383:27490] aSet Count: 1
我要疯了吗?令人惊讶的是,我的整个应用程序几乎都是基于一遍又一遍重复的代码概念。如果我做同样的事情,但使用NSObject
之类的东西,那么问题就会消失,所以它似乎是对SKSprite
的新更改。我知道我可以用一些疯狂的东西来解决它,但这是一个巨大的痛苦,因为我不应该这样做,我希望避免提交另一个版本。
【问题讨论】:
isEqual:
不是(必然)地址比较。用于语义比较;每个类都实现它以定义其特定属性的“平等”是什么。
NSSet
使用-hash
和-isEqual:
来确定成员资格。这仍然与精灵的内存地址没有任何关系。这只是意味着-[SKSprite isEqual:]
的实现在iOS 7和8之间发生了变化,可能远离比较地址和到比较成员数据。
那么问题是,为什么需要使用NSSet
?为什么不是数组?
所以不管怎样,这就是为什么我试图避免说我使用的是 NSset,这样人们就不会说“你为什么使用 NSSet”。我正在使用预先分配的精灵池,因此 NSMutable 集非常适合,因为我不必担心将同一个对象转储回池中
-[NSArray indexOfObjectIdenticalTo:]
会告诉您数组中是否已经存在具有相同 address 的对象。或者您可以继承SKSpriteNode
以在isEqual:
中重新实现地址比较
【参考方案1】:
感谢 Josh 指导如何解决这个新的障碍。
我继承了 SKSpriteNode,覆盖了 -isEqual 和 -hash,这两者都是我对 NSObject 实现的最佳猜测。然后为我的子类名称在“SKSpriteNode”的项目中查找/替换全部,一切都回到了 iOS 7 版本中:
-(BOOL)isEqual:(id)object
return self == object;
- (NSUInteger)hash
return (NSUInteger)self;
【讨论】:
我们应该注意该解决方案的一些副作用吗?我想知道,为什么 Apple 决定在 iOS 8 中为 SKSpriteNode 对象更改 isEqual 行为。 同样适用于 SKNode 类。 没有线索。他们可能会以某种方式依靠平等来处理一些未来的系统。对于我使用 sprite kit 编写的每一行代码,我看不到任何意义。 @Darrarski 我不会担心副作用,正如 Josh Caswell 所提到的,他们似乎将实现从使用内存地址进行比较更改为基于内部设置的实际值生成相等和哈希码SK节点。通常,子节点与节点层次结构中其他位置的其他子节点具有完全相同的值。这意味着当使用 isEqual 和 hash 方法相互比较时,它们看起来是相同的。只要仔细阅读如何正确执行这些方法,自己实现这些方法是完全安全的。以上是关于iOS 8 中的 SKSpriteNode 池似乎分配给了重叠的内存的主要内容,如果未能解决你的问题,请参考以下文章
无法点击 SKSpriteNode - 未检测到触摸 ios