前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【IOS开发进阶系列】APP性能优化专题

【IOS开发进阶系列】APP性能优化专题

作者头像
江中散人_Jun
发布2023-10-16 11:36:25
2690
发布2023-10-16 11:36:25
举报
文章被收录于专栏:云原生布道专栏

1 优化资源文件

        在iOS本地资源文件编译后放置与应用程序包(Bundle)文件中即<应用名>.app文件。

NSBundle *bundle = [NSBundle mainBundle];

NSString *plistPath = [bundle pathForResource:@"team" ofType:@"plist"];

1.1    声音格式优化

1.1.1  iOS平台主要的音频文件格式

        WAV文件,WAV文件格式是一种由微软和IBM联合开发的用于音频数字存储的标准,WAV文件的格式灵活,可以储存多种类型的音频数据。由于文件较大不太适合于移动设备这些存储容量小的设备。

        MP3(MPEG Audio Layer 3)文件,是现在非常流行,MP3是一种有损压缩格式,它尽可能地去掉人耳无法感觉的部分和不敏感的部分。

        CAFF(Core Audio File Format)文件,是苹果开发的专门用于Mac OSX和iOS系统无压缩音频格式。它被设计来替换老的WAV格式。

        AIFF(Audio Interchange File Format)文件,是苹果开发的专门用于Mac OS X系统,是专业的音频文件格式。AIFF的压缩格式是AIFF-C(或AIFC),将数据以4:1压缩率进行压缩,应用于Mac OS X和iOS系统。

1.1.2  背景音乐优化

        文件应该比较小,压缩文件是不错的选择,压缩文件主要是AIFC和MP3可以选择,没有特殊情况我们一定要首选AIFC格式,因为这是苹果推荐的格式。

        原始文件格式不一定是AIFC,这种情况下我们需要使用afconvert工具转换为AIFC格式:

$ afconvert -f AIFC -d ima4 Fx08822_cast.wav

1.1.3  音乐特效优化

        音乐特效很多应用游戏中,当发射子弹、敌人被打死和按钮点击等发出的声音,这些声音都是比较短的,

        如果追求震撼的3D效果,可以采用苹果专用无压缩CAFF格式文件,其它格式的文件尽量不要考虑。

$ afconvert -f caff -d LEI16 Fx08822_cast.wav

1.2    图片格式优化

创建UIImage对象方法的优化

+ imageNamed:类级构造方法,方法会在内存中建立缓存,这些缓存直到应用停止才清除,如果是贯穿于整个应用的图片(如图:图标、logo等)推荐使用。

-initWithContentsOfFile: 实例构造方法,如果是使用一次就基本上不再使用的图片推荐使用该方法。

NSString *path = [[NSBundle mainBundle] pathForResource:@"animal-2" ofType:@"png"];

UIImage *image = [[UIImage alloc] initWithContentsOfFile:path];

... ...

[image release];

// MRR情况下调⽤用

1.3    图片裁切

1.3.1  UIImage自定义绘制的四种方法

///方法中会自动做缩放处理

+(void) getBitmapImage:(UIImage *)image Size:(CGSize)imageSize WithCompletionBlock:(HJCallbackBlock)block

{

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        UIGraphicsBeginImageContextWithOptions(imageSize, YES, 0);

        CGContextRef context = UIGraphicsGetCurrentContext();

        if (!context) {

            dispatch_async(dispatch_get_main_queue(), ^{

                block(image);

            });

        }

        CGRect rect = CGRectMake(0, 0, imageSize.width, imageSize.height);

        //坐标系统已经自动考虑了缩放因素,不需要额外处理

        [image drawInRect:rect blendMode:kCGBlendModeNormal alpha:1];

        UIImage *temp = UIGraphicsGetImageFromCurrentImageContext();

        NSData *tempData = UIImageJPEGRepresentation(temp, 1);

        UIGraphicsEndImageContext();

        //设置SDWebImage库的缓存

        NSString *device = [MDUtility getCurrentDeviceModel];

        if ([device rangeOfString:@"iPhone 4"].length > 0) {

            if (tempData.length > 500000) {

                tempData = UIImageJPEGRepresentation(temp, 0.4);

            }

            temp = [UIImage imageWithData:tempData];

        }

        dispatch_async(dispatch_get_main_queue(), ^{

            if (block) {

                block(temp);

            }

        });

    });

    //    //改进方案1

    //        CGImageRef imgRef = CGImageCreateWithImageInRect(image.CGImage,CGRectMake(0, 0, image.size.width, image.size.height));

    //        UIGraphicsBeginImageContextWithOptions(imageSize, YES, 0);

    //        CGContextRef context = UIGraphicsGetCurrentContext();

    //        CGContextDrawImage(context, imageRect, imgRef);

    //        UIImage *imgData = UIGraphicsGetImageFromCurrentImageContext();

    //        UIGraphicsEndImageContext();

    //        CGImageRelease(imgRef);

    //        UIImage *data = [self verticallyFlipImage: imgData];

    //        return data;

    //方案二,内存有释放,挂机

    //    UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);

    //    CGContextRef context = UIGraphicsGetCurrentContext();

    //    CGRect rect = CGRectMake(0, 0, imageSize.width * [UIScreen mainScreen].scale, imageSize.height * [UIScreen mainScreen].scale);

    //    // draw alpha-mask

    //    CGContextDrawImage(context, rect, image.CGImage);

    //    // draw tint color, preserving alpha values of original image

    //    CGContextFillRect(context, rect);

    //

    //    //Set the original greyscale template as the overlay of the new image

    //    UIImage *imgData = [self verticallyFlipImage:image];

    //    [imgData drawInRect:imageRect];

    //    UIImage *colouredImage = UIGraphicsGetImageFromCurrentImageContext();

    //    UIGraphicsEndImageContext();

    //    CGContextRelease(context);

    //

    //    return colouredImage;

    //方案三,CGBitmapContextCreate方案,内存没释放

    //    CGFloat targetWidth = imageSize.width * [UIScreen mainScreen].scale;

    //    CGFloat targetHeight = imageSize.height * [UIScreen mainScreen].scale;

    //    CGImageRef imageRef = [image CGImage];

    //    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);

    //    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    //    CGContextRef bitmapContext;

    //    bitmapContext = CGBitmapContextCreate(NULL, targetWidth, targetHeight,CGImageGetBitsPerComponent(imageRef),CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    //    CGContextDrawImage(bitmapContext, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);

    //    CGImageRef imgref = CGBitmapContextCreateImage(bitmapContext);

    //    UIImage* newImage = [UIImage imageWithCGImage: imgref];

    //    CGColorSpaceRelease(colorSpaceInfo);

    //    CGContextRelease(bitmapContext);

    //    CGImageRelease(imgref);

    //    return newImage;

    //方案四,CGBitmapContextCreate方案,但是采用CGDataProviderCreateWithCFData方案解决内存占用问题

    //    NSData *data = UIImageJPEGRepresentation(image, 1);

    //    CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);

    //    CGImageRef imageRef = CGImageCreateWithJPEGDataProvider(dataProvider,

    //                                                           NULL, NO,

    //                                                           kCGRenderingIntentDefault);

    //

    //    CGFloat targetWidth = imageSize.width * [UIScreen mainScreen].scale;

    //    CGFloat targetHeight = imageSize.height * [UIScreen mainScreen].scale;

    //    //        CGImageRef imageRef = [image CGImage];

    //

    //    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);

    //

    //    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    //    CGContextRef bitmapContext;

    //    bitmapContext = CGBitmapContextCreate(NULL, targetWidth, targetHeight,CGImageGetBitsPerComponent(imageRef),0, colorSpaceInfo, bitmapInfo);

    //    CGContextDrawImage(bitmapContext, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);

    //

    //    // If failed, return undecompressed image

    //    if (!bitmapContext) return image;

    //

    //    CGImageRef imgref = CGBitmapContextCreateImage(bitmapContext);

    //    UIImage* newImage = [UIImage imageWithCGImage:imgref];//[UIImage imageWithCGImage:decompressedImageRef scale:image.scale orientation:image.imageOrientation];

    //   

    //    CGColorSpaceRelease(colorSpaceInfo);

    //    CGContextRelease(bitmapContext);

    //    CGImageRelease(imgref);

    //   

    //    return newImage;

}

2      延迟加载

2.1    资源文件的延迟加载

非延迟加载方式

延迟加载方式

2.2    故事板和nib文件的延迟加载

2.2.1  故事板的延迟加载

        Segue定义的两个视图控制器的导航关系,也来维护和管理下一个视图控制器的延迟加载时机,这种情况下我们无法“插手”视图控制器的延迟加载。但是一种情况下除外,就是使用了故事板,而控制器之间没有定义导航关系,没有定义Segue。

2.2.2  nib文件延迟加载

        相当于故事板而言nib要灵活的很多,nib文件有两种:一种是描述视图控制器的,另一种是描述视图的,加载方式有所区别。

3      数据持久化的优化

文件

SQLite数据库

CoreData

3.1    使用文件

l  避免多次写入很少的数据,最好是当数据积攒的一定数量,一次写入。

l  将文件读写访问从主线程中剥离出来,由一个子线程负责。

l  写入应该采用增量方式,每次只写入变化的部分,不要为改变几个字节

l  写入整个文件。

3.1.1  文件结构优化

        文件要保存数据,应该是结构化的,苹果中的plist文件就是很好的结构化文件。plist文件结构是层次模型的树形结构,层次的深浅会影响读取/写入的速度。

3.1.2  文件大小优化

l  + dataWithPropertyList: format: options: error: 按照指定的格式和操作参数,序列化属性列表对象到NSData对象。

l  + propertyListWithData: options: format: error: 按照指定的格式和操作参数,从NSData对象反序列化到属性列表对象中。

3.2    使用SQLite数据库

3.2.1  表结构优化

        在iOS这些CPU处理能力低、内存少、存储空间少情况下,我们不能在本地建立复杂表关系,表的个数也不宜超过5个,表中的字段数量也不宜太多。

        移动设备中的数据是不可能是企业级系统数据的全部,它只是企业级系统的补充和扩展。

3.2.2  查询优化
3.2.2.1 索引

        索引能够提供查询性能,哪些字段需要创建索引很关键,这些字段只有在表连接或where条件子句中使用才能提供查询性能;在INTEGER PRIMARY KEY字段上不用建索引,表中数据很少情况下建索引效果不大。

3.2.2.2 限制返回记录数

        在限制返回记录数方面,由于移动设备屏幕相当比较小,屏幕上能显示的数据不多,一次查询出记录数,超过屏幕显示能显示行数,这就没有必须了,也会占用更多的内存、耗费宝贵的CPU时间。因此我们需要为查询添加返回记录数的限制,下面语句是SQLite支持的写法:

SELECT * FROM Note Limit 10 Offset 5;

3.2.2.3 where条件子句

        尽量不用使用Like模糊匹配查询,如果可能则使用“=”号查询。还有尽量不要使用IN语句,可以使用“=”号和or替。还有多个条件中要把非文本的条件放在前面,文本条件放在后面,如下代码:

(salary > 5000000) AND (lastName LIKE 'Guan') 优于 (lastName LIKE 'Guan')AND (salary > 5000000)

3.2.3  插入(或删除)优化

        关闭数据同步 PRAGMA synchronous = OFF,插入完成也可以设置回来PRAGMA synchronous =NORMAL或PRAGMA synchronous = FULL。

        在Objective-C可以调用函数sqlite3_exec实现设置,语句如下:

sqlite3_open(DATABASE, &db);

sqlite3_exec(db, "PRAGMA synchronous = OFF", NULL, NULL, &err);

3.3    使用CoreData

3.3.1  使用存储类型NSSQLiteStoreType

        CoreData的存储类型有NSSQLiteStoreType、NSBinaryStoreType和NSInMemoryStoreType。其中我们注意采用NSSQLiteStoreType类型,这样底层存储就采用了SQLite数据库,SQLite数据库的优点也能发挥出来。

3.3.2  查询优化

        它的查询是通过NSFetchRequest执行Predicate定义的逻辑查询条件实现的,优化规则上与SQLite的where条件子句是一样的。此外,查询返回记录数的限制,可以使用语句:

NSFetchRequest *request = [[NSFetchRequest alloc] init];

//限制⼀一次提取记录数

[request setFetchLimit:10];

//限制提取记录偏移量

[request setFetchOffset:5];

3.3.3  设置PRAGMA指令
3.3.4  Instruments工具中CoreData跟踪模板

4      可重用对象的使用

l  表视图(UITableView)

l  集合视图(UICollectionView)

l  地图视图(MKMapView)

4.1    表视图中的重用对象

4.1.1  表视图单元格

dequeueReusableCellWithIdentifier:和 dequeueReusableCellWithIdentifier:forIndexPath:

dequeueReusableCellWithIdentifier: 方法通过可以中标识符从表视图中获得可重用单元格,模式代码如下。

4.1.2  表视图节头脚视图

        使用表视图的dequeueReusableHeaderFooterViewWithIdentifier:方法获得UITableViewHeaderFooterView对象,如果没有可重用的UITableViewHeaderFooterView对象,则使用initWithReuseIdentifier:构造方法创建。模式代码如下:

4.2    集合视图中的重用对象

4.2.1  单元格视图
4.2.2  补充视图

4.3    地图视图中的重用对象

4.3.1  MKPinAnnotationView对象

5      并发处理与多核CPU

5.1    主线程阻塞问题

ViewController.m中的click:方法

6      编译器和编译参数

6.1    GCC、LLVM GCC与Apple LLVM比较

l  GCC(GNU Compiler Collection,GNU编译器套装),是一套由 GNU 开发的编程语言编译器。也是Linux、Unix及Mac OS X 操作系统的标准编译器,GCC可以编译C、C++、Objective-C、Java和Pascal等语言。

l  LLVM(Low Level Virtual Machine,低级虚拟机),这个虚拟机提供了一套中立的中间代码和编译基础设施,并围绕这些设施提供了一套全新的编译策略(使得优化能够在编译、连接、运行环境执行过。LLVM GCC是 LLVM下编译C、C++和Objective-C编译器。

l  Apple LLVM,是苹果LLVM编译器,2005年开始称为了苹果官方支持的编译器。2010 WWDC(Worldwide Developers Conference,苹果电脑全球研发者大会),苹果公司报告LLVM编译器比GCC编译器快60%。在Xcode 4之后默认采用Apple LLVM编译器。

6.2    Optimization Level

Optimization Level有5个级别

l  -O0,是默认级别,不进行任何的优化,直接将源代码编译到执行文件中,结果不进行任何的重排,编译时间比较长。主要用于调试程序,可以设置断点、改变变量、计算表达式等调试工作。

l  -O1(或-O),是最常用的优化级别,不考虑速度和文件大小权衡问题,与-O0级别相比生成文件更小,可执行的速度更快,编译时间更少。

l  -O2,是在-O1级别基础上再进行优化,增加的指令调度的优化,与-O1级别相比生成文件大小没有变大,编译时间变长了,编译期间占用内存更多了,但程序的运行速度有所提高。该级别是应用程序发布时候的最理想级别,在增加文件大小的情况下提供了最大优化。

l  -O3,是在-O2和-O1级别上再进行优化,该级别可能会提高程序的运行速度,但是也会增加文件的大小。

l  -Os,该种级别用于在有限的内存和磁盘空间下生成尽可能小的文件,由于使用了很好的缓存技术,在某些情况下也会有很快的运行速度。

7      参考资料

iOS优化(一)内存优化经验

http://www.jianshu.com/p/ef52250df748

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 优化资源文件
    • 1.1    声音格式优化
      • 1.1.1  iOS平台主要的音频文件格式
      • 1.1.2  背景音乐优化
      • 1.1.3  音乐特效优化
    • 1.2    图片格式优化
      • 1.3    图片裁切
        • 1.3.1  UIImage自定义绘制的四种方法
    • 2      延迟加载
      • 2.1    资源文件的延迟加载
        • 2.2    故事板和nib文件的延迟加载
          • 2.2.1  故事板的延迟加载
          • 2.2.2  nib文件延迟加载
      • 3      数据持久化的优化
        • 3.1    使用文件
          • 3.1.1  文件结构优化
          • 3.1.2  文件大小优化
        • 3.2    使用SQLite数据库
          • 3.2.1  表结构优化
          • 3.2.2  查询优化
          • 3.2.3  插入(或删除)优化
        • 3.3    使用CoreData
          • 3.3.1  使用存储类型NSSQLiteStoreType
          • 3.3.2  查询优化
          • 3.3.3  设置PRAGMA指令
          • 3.3.4  Instruments工具中CoreData跟踪模板
      • 4      可重用对象的使用
        • 4.1    表视图中的重用对象
          • 4.1.1  表视图单元格
          • 4.1.2  表视图节头脚视图
        • 4.2    集合视图中的重用对象
          • 4.2.1  单元格视图
          • 4.2.2  补充视图
        • 4.3    地图视图中的重用对象
          • 4.3.1  MKPinAnnotationView对象
      • 5      并发处理与多核CPU
        • 5.1    主线程阻塞问题
        • 6      编译器和编译参数
          • 6.1    GCC、LLVM GCC与Apple LLVM比较
            • 6.2    Optimization Level
            • 7      参考资料
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档