在计时器上使用UIView动画时的Swift内存问题

时间:2014-11-13 14:51:10

标签: ios animation memory swift nstimer

我在Xcode 6.1中使用Swift进行编码,并尝试创建一个简单的自动照片幻灯片,在照片之间产生交叉溶解效果。

我认为最好的实现方法是创建一个重复并调用选择器方法的预定NSTimer

@IBOutlet var backgroundImageView: UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()

    backgroundImageView.image = UIImage(named: "1.jpg")

    let backgroundImageTimer = NSTimer.scheduledTimerWithTimeInterval(
        5.0, 
        target: self, 
        selector: "cycleBackgroundImages", 
        userInfo: nil, 
        repeats: true)
}


// Cycling through 9 different photos titled 1.jpg, 2.jpg, ..., 9.jpg
var currentPhotoID = 1
func cycleBackgroundImages() {
    if currentPhotoID < 9 { currentPhotoID++ }
    else { currentPhotoID = 1 }

    let toImage = UIImage(named: "\(currentPhotoID).jpg")
    UIView.transitionWithView(
        self.backgroundImageView, 
        duration: 2.0, 
        options: .TransitionCrossDissolve, 
        animations: { self.backgroundImageView.image = toImage }, 
        completion: nil
     })
}

当我在模拟器上运行时,程序会在每次照片淡入时分配更多内存,直到所有9张照片都消失,然后内存使用量变为450MB左右。使用16GB内存在Mac上运行模拟器时没问题。

但是当我在设备上运行时这是一个问题(在这种情况下是iPhone 6)。系统给我内存警告,一些平滑过渡变得相当不稳定,最终应用程序崩溃。

所以我猜我有3个问题:

  1. 为什么每个动画都使用这么多内存?看起来每个动画平均分配大约50MB,我的图像每个不超过4MB。

  2. 为什么我的应用程序似乎在不再使用图像后保留内存? ARC不会自动释放它们吗?

  3. 有什么方法可以解决这个问题吗?

  4. 感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

正如@rdelmar所说,使用imageWithContentsOfFile:

此外,我还提供了另一种不使用NSTimer()动画的方法,供您参考。

class ViewController: UIViewController {
        @IBOutlet var backgroundImageView: UIImageView!

        override func viewDidLoad() {
                super.viewDidLoad()

                let path = NSBundle.mainBundle().pathForResource("1", ofType: "jpg")
                backgroundImageView.image = UIImage(contentsOfFile: path!)

                cycleBackgroundImages()
        }


        // Cycling through 9 different photos titled 1.jpg, 2.jpg, ..., 9.jpg
        var currentPhotoID = 1
        func cycleBackgroundImages() {
                if currentPhotoID < 9 { currentPhotoID++ }
                else { currentPhotoID = 1 }

                CATransaction.begin()
                CATransaction.setAnimationDuration(2.0)
                CATransaction.setCompletionBlock {
                        let delay = dispatch_time(DISPATCH_TIME_NOW, Int64(5 * NSEC_PER_SEC))
                        dispatch_after(delay, dispatch_get_main_queue()) {
                                self.cycleBackgroundImages()
                        }
                }

                let transition = CATransition()
                backgroundImageView.layer.addAnimation(transition, forKey: kCATransition)
                let path = NSBundle.mainBundle().pathForResource("\(currentPhotoID)", ofType: "jpg")
                backgroundImageView.image =  UIImage(contentsOfFile: path!)

                CATransaction.commit()
        }
}

答案 1 :(得分:0)

UIImageview可以为您创建此类动画,而无需在完成后通过s计时器更改图像。

查看animationImages属性。