- 浏览: 171591 次
- 性别:
- 来自: 济南
最新评论
-
enefry:
如果 请求头是 range bytes=100-100 怎么 ...
[JSP]断点续传多线程链接下载! JSP/Servlet 实现 -
zhw332548183:
请问楼主,为什么 图片截取完毕后,会一直显示 正在保存 ...
从android系统图库中取图片的代码 -
zhw332548183:
请问楼主,为什么 图片截取完毕后,会一直显示 正在保存 ...
从android系统图库中取图片的代码 -
lovebirdegg:
82934162 写道lovebirdegg 写道829341 ...
怎样将xmppframework应用于iphone应用程序开发 -
82934162:
lovebirdegg 写道82934162 写道请问,你现在 ...
怎样将xmppframework应用于iphone应用程序开发
Introduction
So, let’s face it, MANY applications in the app store are “Clunky”. They have jittery interfaces, poor scrolling performance, and the UI tends to lock up at times. The reason? DOING ANYTHING OTHER THAN INTERFACE MANIPULATION IN THE MAIN APPLICATION THREAD!
What do I mean by this? Well, I am essentially talking about multithreading your application. If you don’t know what is meant by multithreading, I suggest you read up on it and return to this post OR don’t worry about it because you don’t need much threading knowledge for this tutorial. Let’s dig in and I’ll give you an example of the problem.
The Problem
When you create an application, the iPhone spawns a new process containing the main thread of your application. All of interface components are run inside of this thread (table views, tab bars, alerts, etc…). At some point in your application, you will want to populate these views with data. This data can be retrieved from the disk, the web, a database, etc… The problem is: How do you efficiently load this data into your interface while still allowing the user to have control of the application.
Many applications in the store simply ‘freeze’ while their application data is being loaded. This could be anywhere from a tenth of a second to much longer. Even the smallest amount of time is noticeable to the user.
Now, don’t get me wrong, I am not talking about applications that display a loading message on the screen while the data populates. In most cases, this is acceptable, but can not be done effectively unless the data is loaded in another thread besides the main one.
Here is a look at the application we will be creating today:
Let’s take a look at the incorrect way to load data into a UITableView from data loaded from the web. The example below reads a plist file from icodeblog.com containing 10,000 entries and populates a UITableView with those entries. This happens when the user presses the “Load” button.
Wrong (download this code here to see for yourself )
@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
“Looks good to me”, you may say. But that is incorrect. If you run the code above, pressing the “Load” button will result in the interface ‘freezing’ while the data is being retrieved from the web. During that time, the user is unable to scroll or do anything since the main thread is off downloading data.
About NSOperationQueue And NSOperation
Before I show you the solution, I though I would bring you up to speed on NSOperation.
According to Apple…
The
NSOperation
andNSOperationQueue
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 anNSOperation
class; theNSOperationQueue
class takes care of starting the operations, ensuring that they are run in the appropriate order, and accounting for any priorities that have been set.
The way it works is, you create a new NSOperationQueue and add NSOperations to it. The NSOperationQueue creates a new thread for each operation and runs them in the order they are added (or a specified order (advanced)). It takes care of all of the autorelease pools and other garbage that gets confusing when doing multithreading and greatly simplifies the process.
Here is the process for using the NSOperationQueue.
- Instantiate a new NSOperationQueue object
- Create an instance of your NSOperation
- Add your operation to the queue
- Release your operation
There are a few ways to work with NSOperations. Today, I will show you the simplest one: NSInvocationOperation. NSInvocationOperation is a subclass of NSOperation which allows you to specify a target and selector that will run as an operation.
Here is an example of how to execute an NSInvocationOperation:
NSOperationQueue * queue = [ NSOperationQueue new] ; NSInvocationOperation * operation = [ [ NSInvocationOperation alloc] initWithTarget: self selector: @selector ( methodToCall) object: objectToPassToMethod] ; [ queue addOperation: operation] ; [ operation release] ;
This will call the method “methodToCall” passing in the object “objectToPassToMethod” in a separate thread. Let’s see how this can be added to our code above to make it run smoother.
The Solution
Here we still have a method being fired when the user presses the “Load” button, but instead of fetching the data, this method fires off an NSOperation to fetch the data. Check out the updated code.
Correct (Download the source code here )
@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] ; }
As you can see, we haven’t added much code here, but we have GREATLY improved the overall user experience. So, what did I do exactly?
- Moved all of the processing (downloading) code from the loadData method to another method that could be run asynchronously
- Created a new instance of NSOperationQueue by calling [NSOperationQueue new]
- Created an NSInvocationOperation to call our method loadDataWithOperation
- Added the operation to the queue
- Released the operation
One thing to note here is we never actually tell the operation to run. This is handled automatically in the queue. The queue will figure out the optimal time run the operation and do it for you.
Now that you have your downloading and processing in a separate thread, you are now free to add things such as a loading view.
I will be expanding on this tutorial in the coming week and showing you how to cache data and display old data to the user while the new is loading. This is a popular technique used in many Twitter and News applications.
That concludes today’s tutorial.
Post questions in the comments or Ping me on Twitter .
Happy iCoding!
发表评论
-
Key-Value Coding. Key-Vaule Observing
2012-02-17 11:41 1259Key-value coding (KVC) 是 ... -
FMDB:我的SQLite救星
2011-08-23 17:08 1306FMDB:我的SQLite救 ... -
统计代码行数
2011-01-04 16:39 2452http://lovebirdegg.appspot. ... -
Universal Static Libraries
2010-04-16 17:02 1121For some reason Apple reserves ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.2(3)
2010-04-16 15:25 1279原文地址:http://www.aisidechina.com ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.2(2)
2010-04-16 15:22 1780原文地址:http://www.aisidechina.com ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.1
2010-04-14 10:27 1750原文地址:http://www.aisid ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.2(1)
2010-04-14 10:25 984原文地址:http://www.aisidechina.com ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.4
2010-04-12 17:16 1171原文地址:http://www.aisid ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.3
2010-04-08 08:10 1395《iPhone应用程序开发 ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.2
2010-04-08 08:09 1422原文地址: http://www.aisidechina. ... -
7 tips for using UIWebView
2010-03-26 14:34 2178For an IPhone app I have been b ... -
how to use TouchXML
2010-03-25 21:50 1647iphoen do not have NSXML* libra ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.1
2010-03-25 12:57 1100原文地址:http://www.aisidechina.com ... -
10 个在app store中需要避免的错误(一)
2010-03-19 18:13 1547原文 #1 Creating an Overly Compl ... -
Filtering Fun with Predicate
2010-03-16 09:34 1521原文:http://lovebirdegg.co.tv/201 ... -
《iPhone应用程序开发指南》第一章 1.1(2)
2010-03-12 17:12 2939原文地址: http://www.aisidechina. ... -
《iPhone应用程序开发指南》第一章 1.1(1)
2010-03-12 17:11 2220原文地址: http://www.aisidechina. ... -
《iPhone应用程序开发指南》目录
2010-03-12 17:09 2173原文地址 http://www.ais ... -
《iPhone应用程序开发指南》介绍
2010-03-12 17:07 2797原文地址 http://www.ais ...
相关推荐
国外针对青少年scratch和python教材,有配套的练习。都是英文版的。
非常适合入门学习用Swift开发iphone apps,强烈推荐。
Oracle Application Express (APEX): Build Powerful Data-Centric Web Apps with APEX features step-by-step application development techniques, real-world coding examples, and best practices. You will ...
NULL 博文链接:https://xxxxxfsadf.iteye.com/blog/563625
turbo码编码转载,,,,,,,,,,,,,,
coding_and_synthesis_with_verilog
关于turbo码的经典书籍,对研究turbo码的人很具有参考价值。
如何有效利用visual studio (05,08,10) *附录
学习LDPC,Turbo编码,信道编码
Turbo+Coding+for+Satellite+and+Wireless+Communications
NULL 博文链接:https://xxxxxfsadf.iteye.com/blog/563653
fixed with placement – the designer has to go back to their RTL code and re-write it to fix the problem. Code it correctly from the beginning, anticipating implementation roadblocks and barriers, ...
微软出版的Coding Faster :Getting More Productive with Microsoft Visual Studio英文原版书 --------------介绍如下------------------ Expert advice to help you work smarter and increase your productivity...
Easy AR Make Awesome AR Apps Without Coding
TITLE: Text of ISO/IEC FCD 29199-2 (JPEG XR image coding – Specification) SOURCE: Gary J. Sullivan and Shankar Regunathan (Microsoft/USA), and Aharon Gill (Zoran/Israel) PROJECT: ISO/IEC 29199-2 ...
A Low Complexity Algorithm for Generating Turbo.pdf
You'll learn how to properly handle forms using WTForms, devise convenient templates with Jinja2 tags and macros, use NoSQL and SQL databases to store user data, test your projects with features and ...
Google IO 2009主题演讲的演讲稿。主要介绍了Android机器的在各种情况下的电源消耗状况,并提出了一些能源是由优化的方法。挺有用的。
turbo码matlab仿真程序,并行级联编码,对于研究信道编码的研究者具有重要参考价值。