Xcode 7/Swift 2.1“来自调试器的消息:由于内存问题而终止”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33967646/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Xcode 7/Swift 2.1 "Message from debugger: Terminated due to memory issue"
提问by rdespoiu
I'm working on a card game in Swift 2.1 using Xcode 7 and my app runs fine in the simulator but crashes when I test it on my device.
我正在使用 Xcode 7 在 Swift 2.1 中开发纸牌游戏,我的应用程序在模拟器中运行良好,但在我的设备上测试时崩溃了。
Using breakpoints, I've pinpointed the crash to an NSTimer.scheduledTimerWithTimeInterval
method that runs after an animation occurs (and then triggers another animation).
使用断点,我将崩溃确定为NSTimer.scheduledTimerWithTimeInterval
在动画发生后运行的方法(然后触发另一个动画)。
I thought maybe it was the size of my images, as some were quite large (>4 MB), so I compressed all the images in the animation, and in total they now take up less than 1 MB.
我想这可能是我的图像的大小,因为有些图像非常大(> 4 MB),所以我压缩了动画中的所有图像,现在它们总共占用了不到 1 MB。
I've also run the Zombie and Leak tools and found nothing, so I'm a little perplexed. Here's the code where it crashes.
我还运行了 Zombie 和 Leak 工具,但一无所获,所以我有点困惑。这是它崩溃的代码。
func animateOnDeal() {
self.playerAnimatedCard.hidden = false
self.dealerAnimatedCard.hidden = true
cardOneToDeal()
}
func cardOneToDeal() {
UIView.animateWithDuration(0.5, animations: {
self.playerAnimatedCard.center.x -= self.view.bounds.width
}, completion: {finished in self.flipCardOne()})
}
func flipCardOne() {
self.playerAnimatedCard.playFlipAnimation()
NSTimer.scheduledTimerWithTimeInterval(0.3, target: self, selector: "cardTwoToDeal", userInfo: nil, repeats: false)
}
And here's the code that actually runs the animation (in a UIImageView subclass):
这是实际运行动画的代码(在 UIImageView 子类中):
func playFlipAnimation() {
self.image = UIImage(named: "cardback2.png")
self.animationImages = nil
var imgArray = [UIImage]()
for var x = 1; x <= 12; x++ {
let img = UIImage(named: "img\(x).png")
imgArray.append(img!)
}
self.animationImages = imgArray
self.animationDuration = 0.3
self.animationRepeatCount = 1
self.startAnimating()
As a side note, the debugger simply states: "Message from debugger: Terminated due to memory issue."
作为旁注,调试器只是声明:“来自调试器的消息:由于内存问题而终止。”
Any help would be greatly appreciated, please let me know if you need any more information. Thanks!
任何帮助将不胜感激,如果您需要更多信息,请告诉我。谢谢!
EDIT:
编辑:
So in order to test it out some more, I changed func playFlipAnimation to iterate and add 5 images instead of the original 12. This seems to have solved the crash, but I'm still unsure as to why having more images is crashing the application in the first place.
因此,为了进行更多测试,我将 func playFlipAnimation 更改为迭代并添加 5 个图像而不是原来的 12 个。这似乎解决了崩溃问题,但我仍然不确定为什么有更多图像会导致应用程序崩溃首先。
采纳答案by Marcus
A couple of points:
几点:
As Derek Lee has already pointed out images can be very memory intensive. In my experience the runtime will also keep images cached in the background for a period after they are used. This could be pertinent to your situation as, looking at your code, you are loading in a fresh set of twelve images every time the animation is called. If you are iterating that animation a lot of times then that will quickly add up to a lot of memory, especially with image files of 1MB. In this case, while it may seem inefficient in the short run you might want to consider initializing an array of images when the class is initialized, which you can reuse.
One thing you can do when iterating over a loop that you know is going to be memory intensive is place it in an autoreleasepool. See the developer reference at: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.htmlI know that technically ARC should be all you need in the modern iOS world but that worked for me when I was building a very data-intensive procedure in one of my apps.
You are unlikely ever to trigger a memory warning running in Simulator as no allowance is made for the fact that the underlying hardware has considerably more capacity available to it than the target device. In my infinite wisdom I once left something running which ended up using 50GB of memory but that did not trigger any kind of warnings on Simulator!
As an aside, I would think you should be able to compress your card images down to far less than 1 MB. Of course this will depend on what kind of image you want to use (are they photos?) but if it is a simple .png, then that seems quite large to me.
正如 Derek Lee 已经指出的那样,图像可能非常占用内存。根据我的经验,运行时还会在使用后将图像缓存在后台一段时间。这可能与您的情况有关,因为查看您的代码,每次调用动画时您都会加载一组全新的 12 张图像。如果您多次迭代该动画,那么这将很快增加大量内存,尤其是 1MB 的图像文件。在这种情况下,虽然在短期内看起来效率低下,但您可能需要考虑在类初始化时初始化图像数组,您可以重用它。
在迭代一个你知道会占用大量内存的循环时,你可以做的一件事是将它放在一个自动释放池中。请参阅开发人员参考:https: //developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html我知道从技术上讲,ARC 应该是现代 iOS 世界中您所需要的一切,但是当我在我的一个应用程序中构建一个非常数据密集型的程序时对我来说有效。
您不太可能触发在模拟器中运行的内存警告,因为没有考虑到底层硬件比目标设备具有更多可用容量这一事实。在我无限的智慧中,我曾经运行过一些东西,最终使用了 50GB 的内存,但这并没有在模拟器上触发任何类型的警告!
顺便说一句,我认为您应该能够将卡片图像压缩到远小于 1 MB。当然,这取决于你想使用什么样的图像(它们是照片吗?)但如果它是一个简单的 .png,那么对我来说似乎相当大。
Hope that helps.
希望有帮助。