- 浏览: 175014 次
- 性别:
- 来自: 济南
最新评论
-
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 1308Key-value coding (KVC) 是 ... -
FMDB:我的SQLite救星
2011-08-23 17:08 1342FMDB:我的SQLite救 ... -
统计代码行数
2011-01-04 16:39 2517http://lovebirdegg.appspot. ... -
Universal Static Libraries
2010-04-16 17:02 1160For some reason Apple reserves ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.2(3)
2010-04-16 15:25 1324原文地址:http://www.aisidechina.com ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.2(2)
2010-04-16 15:22 1821原文地址:http://www.aisidechina.com ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.1
2010-04-14 10:27 1785原文地址:http://www.aisid ... -
《iPhone应用程序开发指南(基础篇)》第六章 6.2(1)
2010-04-14 10:25 1020原文地址:http://www.aisidechina.com ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.4
2010-04-12 17:16 1203原文地址:http://www.aisid ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.3
2010-04-08 08:10 1442《iPhone应用程序开发 ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.2
2010-04-08 08:09 1457原文地址: http://www.aisidechina. ... -
7 tips for using UIWebView
2010-03-26 14:34 2219For an IPhone app I have been b ... -
how to use TouchXML
2010-03-25 21:50 1687iphoen do not have NSXML* libra ... -
《iPhone应用程序开发指南(基础篇)》第三章 3.1
2010-03-25 12:57 1125原文地址:http://www.aisidechina.com ... -
10 个在app store中需要避免的错误(一)
2010-03-19 18:13 1589原文 #1 Creating an Overly Compl ... -
Filtering Fun with Predicate
2010-03-16 09:34 1559原文:http://lovebirdegg.co.tv/201 ... -
《iPhone应用程序开发指南》第一章 1.1(2)
2010-03-12 17:12 2977原文地址: http://www.aisidechina. ... -
《iPhone应用程序开发指南》第一章 1.1(1)
2010-03-12 17:11 2258原文地址: http://www.aisidechina. ... -
《iPhone应用程序开发指南》目录
2010-03-12 17:09 2215原文地址 http://www.ais ... -
《iPhone应用程序开发指南》介绍
2010-03-12 17:07 2844原文地址 http://www.ais ...
相关推荐
这篇“iPhone Coding Tutorial – In Application Emailing”教程将指导开发者如何在iPhone应用程序中集成电子邮件功能,无需离开应用就能发送邮件。这篇博客文章的链接虽然不可用(已替换为示例文本),但我们可以...
《帮助孩子学习计算机编程》是一本面向青少年的计算机编程学习指南,采用了独特的分步视觉指导方式,从最基础的二进制代码教学到最终构建游戏。这本书是国外专为青少年设计的教材,其中涉及了Scratch和Python这两种...
Turbo码是一种具有高效纠错能力的编码技术,广泛应用于通信、存储和数据传输等领域。Turbo码的出现极大地提升了数字通信的可靠性,尤其是在错误率较高的环境中。这个“turbo-matlab.rar”压缩包包含了与Turbo码在...
### Turbo 编码(Turbo Coding) **Turbo编码**是一种高效的前向错误校正技术,主要用于改善数据传输系统的可靠性和性能。它通过并行地使用两个或多个简单的卷积编码器,并在它们之间插入交织器来实现。 #### 卷积...
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 ...
这篇教程“iPhone Coding Tutorial – Inserting A UITextField In A UIAlertViewController”将会教你如何在现代iOS环境中,在警告视图控制器中添加一个文本字段。 首先,我们需要了解`UIAlertController`的基本...
LDPC(低密度奇偶校验)编码和Turbo编码是现代数字通信中的两种重要的信道编码技术。它们的出现大大提高了通信系统中数据传输的效率和可靠性。在深入探讨LDPC和Turbo编码之前,我们首先需要了解数字通信的一些基本...
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, ...
Easy AR Make Awesome AR Apps Without Coding
### Turbo编码在卫星与无线通信中的应用 #### 弔牌:Turbo编码、卫星通信、无线通信 #### 核心知识点解析: ##### 一、引言 - **背景介绍**:随着信息技术的发展,数据传输的需求日益增加,尤其是在卫星通信和...
### 低复杂度算法生成Turbo码随机交织器 #### 摘要 本文提出了一种基于冒泡排序方法的低复杂度算法,该算法可用于生成满足多种标准(如s-随机性、码匹配准则以及Turbo Trellis Coded Modulation中的奇偶属性)的...
【Coding for Battery Life】是2009年Google IO大会上的一次主题演讲,重点讨论了Android设备在不同使用场景下的电力消耗以及如何进行电源优化。电池寿命对于移动设备至关重要,因为它们主要依赖电池运行,而电池...
涡轮码(Turbo码)是一种高效的纠错编码技术,由Berrou等人在1993年提出,被誉为“数字通信的革命”。它以其接近香农极限的优秀性能,在无线通信、卫星通信等领域得到了广泛应用。本资源是针对涡轮码进行MATLAB仿真...
Work through real Swift coding problems that help strengthen your skills – perfect for finding and filling holes in your Swift knowlege, and preparing for iOS interviews.
Spruce up your apps with audio, video, Internet features, stylized text, and more Create applications with the stunning graphics for which Macs are famous See how to build apps with multiple ...
Contains the most recent developments of coded modulation, trellises for codes, soft-decision decoding algorithms, turbo coding for reliable data transmission and other areas. There are two new ...
Contains the most recent developments of coded modulation, trellises for codes, soft-decision decoding algorithms, turbo coding for reliable data transmission and other areas. There are two new ...
### 关于Turbo编码与译码的深入解析 #### 一、引言 在数字通信领域,卷积编码作为一种常见的信道编码技术,在设计数字传输系统时被广泛应用。其主要优势在于通过软输入维特比算法(Soft-Input Viterbi Algorithm, ...