上一张我们做了个UIImageView的帧动画汤姆猫动画,根据进一步的学习发现这里边有很大的内存问题。
如果以前有oc开发经验的,可以很容易的发现这里的问题,但是作者只是个小白,直接学的swift,所以对上篇文章中出的问题表示抱歉。
内存占用过大
var image:UIImage = UIImage(named: imgName)!;
直接通过图片名称加载图片并生成UIImage。此方式加载的图片会缓存到内存中,直到应用退出后才释放。
这样的好处是,再次使用到此图片时,会直接从内存中加载。缺点是,当加载了大量图片时会大量占用内存,导致应用程序内存过大。
经测试,仅仅喝牛奶这个动画就需要200多M的内存。
如何改进
let path = NSBundle.mainBundle().pathForResource(imgName, ofType: nil)!; var image:UIImage = UIImage(contentsOfFile:path)!;
先获得图片路径,在通过路径加载。
注意,通过这种方式加载的,图片不能放到Images.xcassets目录中,只能放大Supporting Files中,否则,无法获得图片路径。如下图:

最后如何释放图片
由于动画结束后self.catIv.animationImages依然会拿着图片数组imgArray的引用,所以imgArray不会自动回收,图片也就不会释放。
所以,动画结束后需要手动清除引用: self.catIv.animationImages = nil;
在objectC中,可以使用performSelector(...)方法,在指定延时后、调用指定方法,来清除引用,但swift中没有这个方法。所以,作为变通,可以使用定时器:
var timer = NSTimer.scheduledTimerWithTimeInterval(9.0, target:self, selector:Selector("disposeImages"), userInfo: nil, repeats:false);即,在延时9秒后调用disposeImages方法:
//释放图片
func disposeImages(){
self.catIv.animationImages = nil;
println("释放了图片");
}好,ok。
完整代码:
import UIKit
class ViewController: UIViewController {
//用于播放的UIImageView
@IBOutlet weak var catIv: UIImageView!;
//喝牛奶
@IBAction func drink() {
//1.加载图片到数组中
var imgArray = [UIImage]();
for var i = 0; i<81; ++i{
var imgName = i<10 ? "drink_0\(i).jpg" : "drink_\(i).jpg";
//通过named方式加载的图片会缓存到内存中,直到应用退出后才释放。
//这样的好处是,再次使用到此图片时,会直接从内存中加载。缺点是,当加载了大量图片时会大量占用内存,导致应用程序内存过大。
//var image:UIImage = UIImage(named: imgName)!;
//推荐的加载图片的使用方式
let path = NSBundle.mainBundle().pathForResource(imgName, ofType: nil)!;
var image:UIImage = UIImage(contentsOfFile:path)!;
imgArray.insert(image, atIndex: i);
}
//2.将数组添加到UIImageView中
self.catIv.animationImages = imgArray;
//3.设置动画持续时间
self.catIv.animationDuration = Double(imgArray.count) * 0.1;
//4.设置动画持续次数
self.catIv.animationRepeatCount = 1;
//5.开启动画
self.catIv.startAnimating();
//释放图片
// let timer = NSTimer(timeInterval:3, target:self, selector:"disposeImages:", userInfo: nil, repeats:false);
// timer.fire();
var timer = NSTimer.scheduledTimerWithTimeInterval(9.0, target:self, selector:Selector("disposeImages"), userInfo: nil, repeats:false);
//timer.fire();
}
//吃东西
@IBAction func eat() {
//1.加载图片到数组中
var imgArray = [UIImage]();
for var i = 0; i<40; ++i{
var imgName = i<10 ? "eat_0\(i)" : "eat_\(i)";
//var image:UIImage = UIImage(named: imgName)!;
let path = NSBundle.mainBundle().pathForResource(imgName, ofType: "jpg")!;
var image:UIImage = UIImage(contentsOfFile:path)!;
imgArray.insert(image, atIndex: i);
}
//2.将数组添加到UIImageView中
self.catIv.animationImages = imgArray;
//3.设置动画持续时间
self.catIv.animationDuration = Double(imgArray.count) * 0.1;
//4.设置动画持续次数
self.catIv.animationRepeatCount = 1;
//5.开启动画
self.catIv.startAnimating();
var timer = NSTimer.scheduledTimerWithTimeInterval(9.0, target:self, selector:Selector("disposeImages"), userInfo: nil, repeats:false);
}
//释放图片
func disposeImages(){
self.catIv.animationImages = nil;
println("释放了图片");
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}