`
亚当爱上java
  • 浏览: 705154 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

iPad app应用开发系列文章之三 -- iOS的多核编程和内存管理[转]

 
阅读更多
隔上一次写iPad app开发文章已经是10个月,那篇iPad app开发概述还不错,曾经成为了google关键字“iPad app 开发”搜索的第一位,可能是大牛们都太忙于赚app store的钱了,留下我这个小虾来写文章。这次的文章集中与iOS的多核编程和内存管理,为什么?因为iPad 2已经是双核CPU了!虽然iPad 1的应用已经不慢了,但大家完全可以使用苹果的多核编程框架来写出更加responsive的应用。



多核运算

在iOS中concurrency编程的框架就是GCD(Grand Central Dispatch), GCD的使用非常简单。它把任务分派到不同的queue队列来处理。开发者把任务代码装到一个个block里面,操作系统把这些任务代码分派到不同的资源里去处理,一个简单的例子来说,为什么初学者写tableview的时候,滑动列表时总会很卡,因为很多初学者把图片装载放到main thread主线程去执行,例如我们要滑动畅顺的话,iOS最快可以1秒内刷新60次,如何你的一个cell的文字和图片装载超过1/60秒的话,自然就会卡。所以一般我们会把图片装载这些需要多点时间的移出main thread来处理,对于用GCD来说,就是把图片载入放到另外一个queue队列中来异步执行,当资源准备好了后,放回到main thread中显示出来。main thread在GCD中就是main queue。



创建一个新queue队列的代码:

dispatch_queue_t network_queue;

network_queue = dispatch_queue_create("com.myapp.network", nill);

例如,我们图片读取放到network_queue来进行异步执行

dispatch_async(network_queue, ^{  
    UIImage *cellImage = [self loadMyImageFromNetwork:image_url];  
    // 将图片cache到本地  
    [self cacheImage:cellImage];  
  
    .....  
      
} );

dispatch_async的意思就是将任务进行异步并行处理,不一定需要一个任务处理完后才能处理下一个。以上代码loadMyImageFromNetwork的意思就是从网络中读取图片,这个任务交给network_queue来处理。这样读取图片的时间过长也不会阻塞主线程界面的处理。



当我们处理完图片后,应该更新界面,从queue的概念去设计,就是要将更新界面的代码放到main queue中去,因为iOS里面永远是主线程来刷新重画UI。所以代码应该为,

[dispatch_async(network_queue, ^{  
 	UIImage *cellImage = [self loadMyImageFromNetwork:image_url];  
    // 将图片cache到本地  
    [self cacheImage:cellImage];  
  
   // 回到主线程  
   dispatch_async(dispatch_get_main_queue(), ^{  
      // 显示图片到界面  
      [self displayImageToTableView:cellImage];  
   }];  
      
} );

dispatch_get_main_queue() 函数就是返回主线程,^{} 封装的就是任务代码,这样嵌套方式就可以从一个队列queue,跳到另一个queue,就是这么简单。



我们一般可以把networking有关的代码放到一个queue,把图片resize的代码放到另外一个queue,处理完后更新界面,只需要嵌套跳回到 main queue。这样加上几行代码,你的程序就可以利用到系统多核资源,把具体的调度工作交给了操作系统自己来分配。有了这样的代码,不管你的硬件是单核,双核还是iMac的4核,甚至8核,都可以非常好地并行处理。





内存管理

我一直惊叹iOS和Objective-C内存处理能力,例如iPad版本的iWork,Pages应用就是一个内存处理技术应用的鬼斧神工之作。想想256M内存的iPad,可以带来如此的华丽的界面同时获得如此流畅的用户体验,真是不简单。原因就是iOS一直提倡开发者在有限硬件资源内写出最优化的代码,使用CPU最少,占用内存最小。



(以下代码适用于iOS SDK 4.1, 由于新SDK 4.2对内存使用有新改动,所以可能有不同。。。)

1. 尽量少的UIView层

通常我们喜欢把很多控件层(UILabel,UIButton,UIView等)一起放到一个大的UIView容器来显示我们的内容,这个方法一般是可以的,但是如果要经常重新刷新内容的大区域界面,多数发生在iPad的应用中,这个方法会带来过多的内存使用和动画的延迟(比较卡),例如,scrollview的动画比较卡,又或者,经常收到内存警告。其中一个重要原因是每个控件,特别是透明底的,会多次重新绘制(drawRect)过多。其解决办法是,尽量将几个控件合并到一个层上来显示,这样系统会减少系统调用drawRect,从而带来性能上的提升。



很简单的一个例子,就是iNotes提供手写功能,用户可以在iPad屏幕上写出不同的笔画,开始的设计是,用户每写一划,iNotes就会生成一个新的透明底UIView来保持这个笔画,用户写了10笔,系统就生产了10个UIView,每个view的大小都是整个屏幕的,以便用户的undo操作。这个方案带来严重的内存问题,因为系统将每个层都保持一个bitmap图,一个像素需要4bit来算,一个层的大小就是 4x1024x768 ~ 3M, 10个层就是 10x3M = 30M,很明显,iPad很快爆出内存警告。



这个例子最后的方案是,所有笔画都画在同一个层,iNotes可以保存笔画的点进行undo操作。这样的方案就是无论用户画多少笔画,界面重画需要的资源都是一样的。



2. 显示最佳尺寸的图片

很多程序员比较懒,网络上拿下来的图片,直接就用UIImageView将其显示给用户,这样的后果就是,程序需要一直保存着大尺寸的图片到内存。解决办法应该是先将图片缩小到需要显示的尺寸,释放大尺寸图片的内存,然后再显示到界面给用户。



3. 尽量使用图片pattern,而不是一张大的图片

例如,很多界面设计者喜欢在界面上放一个大底图,但这个底图是老是占用着内存的,最佳方案是,设计出一个小的pattern图,然后用这个方案显示成底图。

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

backgroundView.backgroundColor = [UIColor colorWithPatternImage:smallImage];

[smallImage release];

4. 使用完资源后,立即释放

一般objective-c的习惯是,用完的资源要立即释放,因为明白什么时候用完某个资源的是程序员你自己。

例如,我们要读较大的图片,把它缩小后,显示到界面去。当大图片使用完成后,应该立即释放。代码如下:
UIImage *fullscreenImage = [[UIImage alloc] initWithContentOfFile:path];
UIImage *smallImage = [self resizeImage:fullscreenImage];

[fullscreenImage release];

imageView.image = smallImage;

......


5. 循环中大量生成的自动释放autorelease对象,可以考虑使用autorelease pool封装

代码范例:

for(UIView *subview in bigView.subviews) {
    // 使用autorelease pool自动释放对象池
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    UIImageView *imageView = (UIImageView *)subview;
    
    // subview处理代码
    .......

    // 销毁自动释放对象
    [pool  drain];
}
分享到:
评论

相关推荐

    ios开发详解markdown格式

    - **Grand Central Dispatch (GCD)**:GCD是一个多核编程的解决方案,可以帮助开发者优化应用性能,使其能够高效地处理多个任务。 #### 五、最佳实践 - **架构模式**:推荐使用MVC (Model-View-Controller) 或 ...

    swift-学习和分享iOS开发的知识和经验

    在Swift学习和分享iOS开发的过程中,我们涉及到一系列关键知识点,这些知识构成了iOS应用程序开发的基础。首先,Swift语言是苹果公司推出的编程语言,专为iOS、iPadOS、macOS、watchOS和tvOS平台设计,它提供了简洁...

    swift-iOS开发直播App集合了ios开发各种常用功能与技巧

    综上所述,"iCocosLive-master"项目涵盖了从基础的Swift语法到复杂的多媒体处理、网络通信等iOS开发的诸多方面,是学习和实践iOS直播应用开发的宝贵资源。通过深入研究和实践这个项目,开发者可以提升自己的Swift...

    一款虫部落搜索论坛第三方 iOS App,使用 SwiftUI 开发,采用最新的 Swift Concurrency 并发技术

    标题中的“一款虫部落搜索论坛第三方 iOS App”指的是一个由开发者独立制作的应用程序,它针对虫部落搜索论坛提供了专门的iOS界面。这个App是用 SwiftUI 框架编写的, SwiftUI 是苹果公司推出的用于构建 iOS、macOS...

    ios开发从入门到精通pdf

    Swift是一种安全、高效且易于学习的编程语言,适用于开发iOS、macOS、watchOS和tvOS应用。 - **语法简介**:Swift借鉴了C和Objective-C的优点,并吸收了现代语言的最佳实践。 - **变量与常量**:变量使用`var`声明...

    ipad基础开发教程Beginning_Ipad

    1. **iOS SDK**:iOS软件开发工具包是iPad应用开发的基础,它包含了一整套开发环境、调试工具和框架,如Xcode IDE,Interface Builder,以及Objective-C和Swift编程语言。 2. **Objective-C和Swift**:iPad应用开发...

    Objective-C新手入门

    完成应用开发后,开发者需要遵循Apple的App Store审核指南,提交应用进行审核。审核通过后,应用才能在App Store上架供用户下载。 九、持续学习与进阶 Objective-C的学习不应止步于入门,深入研究Cocoa设计模式、...

    ipad客户端

    iPad客户端是指专为苹果公司的平板电脑iPad设计和开发的应用程序,允许用户在iPad上享受各种功能和服务。iPad客户端开发是IT行业中一个特定的领域,它涉及到iOS操作系统、Swift编程语言、用户界面设计以及性能优化等...

    IOS Hacker

    用户应该定期更新系统和应用,避免安装来源不明的应用程序。 综上所述,IOS设备的安全性是一个复杂而动态的过程,涉及到硬件、软件以及用户行为等多个方面。苹果公司通过不断的技术创新和政策调整,努力为用户提供...

    苹果 cocoa编程教程

    苹果的Cocoa编程教程是针对Mac、iPad以及iPhone应用开发的重要资源,对于想要涉足Apple生态系统的开发者来说,这是一个深入理解Objective-C和Swift编程语言,以及iOS和macOS平台框架的关键入口。Cocoa是Apple的原生...

    tom2 app settings

    标题“tom2 app settings”和描述“tom2 cat unlock setting”提及的是一个关于Tom2应用程序的设置和解锁配置。在iOS设备,特别是iPad HD(高清版)上,这个可能指的是一个定制的应用程序或游戏,其内部包含了特定的...

    Cocoa and Objective-C

    11. **App生命周期和内存管理**:理解应用的启动、运行、暂停、恢复和终止过程,以及ARC(Automatic Reference Counting)内存管理机制,是防止内存泄漏和确保应用稳定运行的关键。 通过学习以上知识点,并结合提供...

    iOS版

    iOS操作系统以其用户友好性和安全性而闻名,因此iOS应用开发具有独特的挑战和机遇。下面,我们将深入探讨iOS版开发的一些核心知识点。 1. **Swift编程语言**:Swift是Apple于2014年推出的编程语言,用于替代...

    编写苹果游戏中心应用程序

    GCD则是一个多核编程模型,用于调度任务到不同的线程或队列中。 - **理解块对象**:块对象允许你在代码中定义一段可执行的代码片段,然后将其作为参数传递给其他方法。GameKit中的许多方法都接受块对象作为参数,当...

Global site tag (gtag.js) - Google Analytics