原文地址:使用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的过程:
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”按钮时界面是否还被“冻结”呢,程序并没有增加很多的代码,但确大大的提高了用户体验。
一直在模拟器上做的android开发,最近需要在ophone上实现一个services应用程序,手头刚好有一部LG GW880的手机,兴冲冲地想把自己的应用装到上面测试一下,却老是出现“无法在手机上安装应用程序”的警告,很是纳闷,最后G鱼大
神告知说需要做一个自签名的keystore,用这个keystore生成一个签名后的应用才可以安装,感觉比较神奇,原来做javame和symbian都需要money才能做签名,这会竟然可以这样搞。
如果没有keystore,可以选中android tools后选择export signed application package,之后选择create new keystore,在弹出的location中选择生成一个.keystore的文件(如blessdyb.keystore),输入密码后下一项就是输入各种keystore的详细信息,按说明随便填写就可以了。
在生成这个keystore文件后,我们再次选择export signed application package后使用我们刚才生成的keystore文件就可以生成一个singed package application了。呵呵,试了一下,不论android1.5上开发的应用还是ophone1.5上开发的应用都可以通过这种方式实现真机部署。
手头的笔记本装的是64位瘟7,无法使用友善胳膊提供的u sb写入驱动。所以第一步是配置个操作它的环境,使用不存在的盒子加得必安。
其中不存在的盒子的串口1配置使用host device,设备名COM1。
# apt-get install libusb-dev bzip2 make gcc
# wget http://mini2440.googlecode.com/files/s3c2410_boot_usb-20060807.tar.bz2
# tar xf s3c2410_boot_usb-20060807.tar.bz2
# cd s3c2410_boot_usb
# make
# chmod a+x s3c2410_boot_usb
# mv s3c2410_boot_usb /usr/local/bin/
晚上回去试试u sb连接,再写下一段……
好吧,假的终不如真的,弄了个台式机装系统,才把u sb搞定。