`
lovebirdegg
  • 浏览: 175045 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

使用NSOperation为你的app加速

阅读更多

原文地址:使用NSOperation为你的app加速
在app store中的很多应用程序非常的笨重,他们有好的界面,但操作性很差,比如说当程序从网上或本地载入数据的时候,界面被冻结了,用户只能等程序完全载入数据之后才能进行操作。
当打开一个应用程序时,iphone会产生一个包含main方法的线程,所用程序中的界面都是运行在这个线程之中的(table views, tab bars, alerts…),有时候我们会用数据填充这些view,现在问题是如何有效的载入数据,并且用户还能自如的操作程序。
下面要说方法的并不是要在用户载入数据的时候在界面上提示“loading”的信息,虽然这种方式在有些时候是可以被接受的,但当数据在main线程之外被载入是并不是最有效的方式。
先看一下要演示的程序:


这个程序将从网络上下载10,000条数据,并填入到UITableView中,现面的代码将首先演示一种错误的方式:
错误 (源码 )

 
@implementation

 RootViewController
@synthesize

 array

;
 
-

 (

void

)

viewDidLoad {


[

super viewDidLoad]

;
 
/* Adding the button */


self

.navigationItem.rightBarButtonItem =

 [

[

UIBarButtonItem alloc

]

 initWithTitle

:

@"Load"


style

:

UIBarButtonItemStyleDone
target

:

self


action

:

@selector

(

loadData)

]

;
 
/* Initialize our array */


NSMutableArray

 *

_array =

 [

[

NSMutableArray

 alloc

]

 initWithCapacity

:

10000

]

;
self

.array

 =

 _array;
[

_array release

]

;
}


 
// Fires when the user presses the load button


-

 (

void

)

 loadData {


 
/* Grab web data */


NSURL

 *

dataURL =

 [

NSURL

 URLWithString

:

@"http://icodeblog.com/samples/nsoperation/data.plist"

]

;
 
NSArray

 *

tmp_array =

 [

NSArray

 arrayWithContentsOfURL

:

dataURL]

;
 
/* Populate our array with the web data */


for

(

NSString

 *

str in

 tmp_array)

 {


[

self

.array

 addObject

:

str]

;
}


 
/* reload the table */


[

self

.tableView

 reloadData

]

;
}


 
#pragma mark Table view methods


 
-

 (

NSInteger)

numberOfSectionsInTableView:

(

UITableView *

)

tableView

 {


return

 1

;
}


 
-

 (

NSInteger)

tableView

:

(

UITableView *

)

tableView

 numberOfRowsInSection:

(

NSInteger)

section {


return

 [

self

.array

 count

]

;
}


 
-

 (

UITableViewCell *

)

tableView

:

(

UITableView *

)

tableView

 cellForRowAtIndexPath:

(

NSIndexPath

 *

)

indexPath {


 
static

 NSString

 *

CellIdentifier =

 @"Cell"

;
 
UITableViewCell *

cell

 =

 [

tableView

 dequeueReusableCellWithIdentifier:

CellIdentifier]

;
if

 (

cell

 ==

 nil

)

 {


cell

 =

 [

[

[

UITableViewCell alloc

]

 initWithStyle:

UITableViewCellStyleDefault
reuseIdentifier:

CellIdentifier]

 autorelease

]

;
}


 
/* Display the text of the array */


[

cell

.textLabel setText:

[

self

.array

 objectAtIndex

:

indexPath.row

]

]

;
 
return

 cell

;
}


 
-

 (

void

)

dealloc

 {


[

super dealloc

]

;
[

array

 release

]

;
}


 
@end


 

当点击“load”按钮时程序会被冻结,直到将数据完全下载并填入Tableview,在这期间用户不能做任何的事情。
在给出解决方式之前先来看一下NSOperationQueue和NSOperation:
The NSOperation and NSOperationQueue classes  alleviate much of the pain of multi-threading, allowing you to simply  define your tasks, set any dependencies that exist, and fire them off.  Each task, or operation , is represented by an instance  of an NSOperation class; the NSOperationQueueclass  takes care of starting the operations, ensuring that they are run in  the appropriate order, and accounting for any priorities that have been  set.
下面要做的是建立NSOperationQueue和NSOperations。NSOperationQueue会建立一个线程,每个加入到线程operation会有序的执行。
下面是使用NSOperationQueue的过程:
  1. 建立一个NSOperationQueue的对象
  2. 建立一个NSOperation的对象
  3. 将operation加入到NSOperationQueue中
  4. release掉operation
使用NSOperation有几种,现在介绍最简单的一种NSInvocationOperation,NSInvocationOperation是NSOperation的子类,允许运行在operation中的targer和selector。  下面是执行NSInvocationOperation的一个例子:
 
NSOperationQueue

 *

queue =

 [

NSOperationQueue

 new

]

;
 
NSInvocationOperation

 *

operation

 =

 [

[

NSInvocationOperation

 alloc

]

 initWithTarget

:

self


selector

:

@selector

(

methodToCall)


object

:

objectToPassToMethod]

;
 
[

queue addOperation:

operation

]

;
[

operation

 release

]

;
 
 

下面是我们用正确的方式实现的程序:
正确的方式(下载源码 )
 
@implementation

 RootViewController
@synthesize

 array

;
 
-

 (

void

)

viewDidLoad {


    [

super viewDidLoad]

;
 
    self

.navigationItem.rightBarButtonItem =

 [

[

UIBarButtonItem alloc

]

 initWithTitle

:

@"Load"


       style

:

UIBarButtonItemStyleDone
       target

:

self


       action

:

@selector

(

loadData)

]

;
 
    NSMutableArray

 *

_array =

 [

[

NSMutableArray

 alloc

]

 initWithCapacity

:

10000

]

;
    self

.array

 =

 _array;
    [

_array release

]

;
}


 
-

 (

void

)

 loadData {


 
    /* Operation Queue init (autorelease) */


    NSOperationQueue

 *

queue =

 [

NSOperationQueue

 new

]

;
 
    /* Create our NSInvocationOperation to call loadDataWithOperation, passing in nil */


    NSInvocationOperation

 *

operation

 =

 [

[

NSInvocationOperation

 alloc

]

 initWithTarget

:

self


        selector

:

@selector

(

loadDataWithOperation)


        object

:

nil

]

;
 
    /* Add the operation to the queue */


    [

queue addOperation:

operation

]

;
    [

operation

 release

]

;
}


 
-

 (

void

)

 loadDataWithOperation {


    NSURL

 *

dataURL =

 [

NSURL

 URLWithString

:

@"http://icodeblog.com/samples/nsoperation/data.plist"

]

;
 
    NSArray

 *

tmp_array =

 [

NSArray

 arrayWithContentsOfURL

:

dataURL]

;
 
    for

(

NSString

 *

str in

 tmp_array)

 {


        [

self

.array

 addObject

:

str]

;
    }


 
    [

self

.tableView

 reloadData

]

;
}


 
#pragma mark Table view methods


 
-

 (

NSInteger)

numberOfSectionsInTableView:

(

UITableView *

)

tableView

 {


    return

 1

;
}


 
-

 (

NSInteger)

tableView

:

(

UITableView *

)

tableView

 numberOfRowsInSection:

(

NSInteger)

section {


    return

 [

self

.array

 count

]

;
}


 
-

 (

UITableViewCell *

)

tableView

:

(

UITableView *

)

tableView

 cellForRowAtIndexPath:

(

NSIndexPath

 *

)

indexPath {


 
    static

 NSString

 *

CellIdentifier =

 @"Cell"

;
 
    UITableViewCell *

cell

 =

 [

tableView

 dequeueReusableCellWithIdentifier:

CellIdentifier]

;
    if

 (

cell

 ==

 nil

)

 {


        cell

 =

 [

[

[

UITableViewCell alloc

]

 initWithStyle:

UITableViewCellStyleDefault reuseIdentifier:

CellIdentifier]

 autorelease

]

;
    }


 
    [

cell

.textLabel setText:

[

self

.array

 objectAtIndex

:

indexPath.row

]

]

;
 
    return

 cell

;
}


 
-

 (

void

)

dealloc

 {


    [

super dealloc

]

;
    [

array

 release

]

;
}


 

再次运行程序,当点击“load”按钮时界面是否还被“冻结”呢,程序并没有增加很多的代码,但确大大的提高了用户体验。

分享到:
评论
2 楼 faye.feelcool 2011-02-28  
这排版,无法看了。
1 楼 tnzi 2011-02-18  
[self performSelector:@selector(loadDataWithOperation) withObject:nil afterDelay:0.1];   速度比你快5倍

相关推荐

    NSOperation

    NSOperation是苹果iOS和macOS开发中的一个关键概念,它属于Foundation框架,是Apple为解决多线程和并发问题提供的一种高级抽象。在iOS和macOS应用开发中,特别是处理像UITableView这样的视图组件时,高效地加载和...

    iOS 多线程NSoperation

    每个NSOperation对象都有一个isCancelled属性,可以在操作执行过程中检查这个属性,如果为YES,则意味着操作已被取消,开发者应该尽快清理资源并结束操作。 六、KVO(Key-Value Observing) NSOperation实现了KVO...

    iOS多线程应用开发中使用NSOperation类的基本方法

    NSOperation是一个抽象类,其主要作用是为多线程编程提供了一种更加灵活的解决方案。与直接使用GCD(Grand Central Dispatch)相比,NSOperation提供了更丰富的特性,如依赖管理、取消任务、操作优先级等。要使用...

    NSOperation例子

    NSOperation是苹果iOS和macOS开发中的一个关键概念,它属于Foundation框架,是Apple为解决多线程问题提供的一种高级接口。NSOperation是基于GCD(Grand Central Dispatch)的一个抽象层,它允许开发者以更面向对象的...

    NSOperationDemo

    NSInvocationOperationViewController: NSOperation 的子类 NSInvocationOperation 线程的基本使用 NSBlockOperationViewController: NSOperation 的子类 NSBlockOperation 线程的基本使用 ...

    同步和异步的NSOperation的Demo

    你可以通过继承NSOperation来创建自定义的操作类,或者直接使用Apple提供的子类,如NSInvocationOperation和NSBlockOperation,来快速执行简单的任务。在NSOperation中,你可以添加依赖关系,控制操作的执行顺序,...

    iOS多线程与网络开发之NSOperation示例代码

    NSOperation的基本使用 1.NSOperation的作用 配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation对象中 然后...

    演示多线程加载图片NSThread NsOperation GCD

    我们可以创建自定义的`NSOperation`子类,或者使用苹果提供的`NSBlockOperation`,如下所示: ```swift let operation = NSBlockOperation(block: { self.loadImage() }) operationQueue.addOperation(operation) ...

    NSOperation_NSOperationQueue_Demo

    你可以通过继承自NSOperation创建自定义操作,或者使用苹果提供的子类,如NSInvocationOperation(用于包装block或方法调用)和NSBlockOperation(直接在其中添加执行代码的block)。 **NSOperation的特性:** 1. *...

    Objective-C的NSOperation多线程类基本使用指南剖析.pdf

    例如,如果你有一个名为`run`的方法,可以这样创建和启动操作: ```objc NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil]; ...

    OC-NSOperation异步线程下载图片

    本篇文章将深入探讨如何使用`OC-NSOperation`来实现异步线程下载图片。 首先,我们需要了解`NSOperation`的基本概念。它是`Foundation`框架的一部分,提供了对并发操作的抽象,可以将一个任务表示为一个操作对象。`...

    iOS-多线程之NSOperation - iOS知识库1

    总之,NSOperation和NSOperationQueue为iOS开发者提供了一种高效、易用的方式来实现多线程编程,它们提供了取消、依赖关系、自定义行为等功能,使得处理复杂任务变得更加简单。在实际开发中,可以根据需求选择合适的...

    iOS NSThread和NSOperation的基本使用详解

    本文将深入探讨两种常见的多线程实现方式:NSThread和NSOperation,并讲解它们的基本使用方法。 首先,我们来看一下NSThread。NSThread是苹果提供的轻量级线程管理类,适用于处理简单、独立的耗时任务。它提供了两...

    ios (线程 iphone 并发 异步 NSOperation)介绍

    - 使用`NSOperation`或`DispatchQueue`来并发执行循环中的任务。 **5.4 替换线程Join** - **问题**:线程Join会导致主线程阻塞。 - **解决方案**:使用`dispatch_group_wait`来等待一组任务完成。 **5.5 修改...

    iOS开发 - 第04篇 - 网络 - 01 - NSOperation & 网络基础

    NSOperation是Apple提供的一种高级任务调度机制,它为并发编程提供了强大而灵活的支持,尤其适合处理网络请求。下面我们将深入探讨这两个主题。 首先,我们来看NSOperation。它是Foundation框架的一部分,提供了对...

    NSOperation-Network-Demo:关于如何使用 NSOperation 子类进行异步网络调用的小演示

    通过这个 demo,你可以学习到如何在实践中结合 NSOperation 和网络请求,提升 iOS 应用的并发处理能力,同时保持代码的清晰和可维护性。记得这只是一个演示,实际开发中还需要考虑更多的细节和测试,以确保稳定性和...

    使用GCD和NSOperation的自我感悟(部分用法和tips)

     NSOperation和NSOperationQueue:其实出现得比GCD更早,但是GCD出现以后苹果在GCD的基础上对NSOperation进行了重写,使其对象化,符合了大众开发者的习惯。作为更高层的技术,NSOperation在处理依赖关系、控制各种...

    Objective-C的NSOperation多线程类基本使用指南

    NSOperation本身是抽象基类,因此必须使用它的子类,使用NSOperation子类的方式有2种: 1> Foundation框架提供了两个具体子类直接供我们使用:NSInvocationOperation和NSBlockOperation 2> 自定义子类继承NSOperation...

Global site tag (gtag.js) - Google Analytics