问题
I'm coding with Swift in Xcode 6.1 and trying to create a simple automatic photo slideshow with a cross-dissolve effect between photos.
I figured the best implementation would be to create a scheduled NSTimer that repeats and calls a selector method
@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
})
}
When I run on the simulator, the program allocs more memory each time a photo is faded in until all 9 photos are faded through and then the memory usage flattens out at around 450MB. That's no problem when running using the simulator on my Mac with 16GB of memory.
But it is a problem when I run on the device (iPhone 6 in this case). The system gives me memory warnings, some of the smooth transitions become fairly choppy, and eventually the application crashes.
So I guess I have 3 questions:
Why does each animation use so much memory? It looks like each animation allocs maybe around 50MB on average and my images are each no larger than 4MB.
Why does my app seem to hold on to the memory after the images are no longer used? Doesn't ARC free them automatically?
Is there any way to fix this?
Thanks for your help!
回答1:
As @rdelmar said, use imageWithContentsOfFile:
.
In addition, I provide you an alternative way to do the animation without using a NSTimer()
, for your reference.
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()
}
}
回答2:
UIImageview can create such animations for you without having to go through and change the images with s timer as you've done.
Have a look at the animationImages
property.
来源:https://stackoverflow.com/questions/26911663/swift-memory-issues-when-using-uiview-animation-on-a-timer