最近发现某些皮肤在iOS版岁寒输入法下会出现莫名其妙崩溃的情况,经分析研究,发现是由于皮肤中的素材太大,导致加载时程序内存占用暴涨而崩溃(iOS下的输入法运行内存限制大约为40mb,一不小心就会爆)。解决方案是在加载图片时对图片做压缩处理。

虽然Xamarin.iOS基本上是对原生iOS平台API的封装,但Xamarin在封装时对API的命名方法做了调整,因此有时候我们并不知道,原生平台上的API对应到Xamarin.iOS上时哪一个。


下面介绍一下Xamarin.iOS中图片压缩的两种方法:

方法1:

调用UIImageJPEGRepresentation和UIImagePNGRepresentation方法对图片做处理,在Xamarin.iOS中与之对应的方法分别是AsJPEG和AsPNG。

使用方法如下:

//NSData nsdata = image. AsPNG();
NSData nsdata = image.AsJPEG();
UIImage newImage = new UIImage(nsdata);

其中AsPNG不带参数,因此不能进一步压缩图片,而AsJPEG有一个重载版本可以设置压缩因子:

AsJPEG的压缩效果要好于AsPNG。但我们知道JPEG是不支持alpha通道的,因此AsJPEG会使图片变成不透明图片,因此想要保持图片的透明效果就不能使用AsJPEG;

方法2:

我们可以将图片绘制到一张长宽小一些的图片上,从而压缩图片的体积;

代码如下:

UIImage newImage = oldImage;
var height = (float)oldImage.Size.Height;
height = TRANFORM_HEIGHT;
var width = (float)(oldImage.Size.Width * (TRANFORM_HEIGHT / oldImage.Size.Height));

UIGraphics.BeginImageContext(new SizeF(width, height));
oldImage.Draw(new CoreGraphics.CGRect(0, 0, width, height));
newImage = UIGraphics.GetImageFromCurrentImageContext();
UIGraphics.EndImageContext();
oldImage.Dispose();
oldImage = null;
GC.Collect();//命令GC立即回收内存,在同时压缩多张图片时避免内存占用出现巨大峰值,如果只是转换一两张图片,则无必要;

其中TRANFORM_HEIGHT为想要转换成的目标高度;UIGraphics.BeginImageContext对应原生API中的UIGraphicsBeginImageContext方法,后面的几个方法也是类似的,这种将前缀提取出来的做法在Xamarin.iOS中比较常见。


以上,希望对读者能有帮助。