IOS block concurrency2012-06-13 09:31 1351 people read comments (0) favorite reports Iosuiviewnetwork Task Threadimage
This article goes from http://anxonli.iteye.com/blog/1097777, which focuses on multi-core programming and memory management with iOS, and you can use Apple's multicore programming framework to write more responsive applications.
Multi-core operations
The framework for concurrency programming in iOS is GCD (Grand Central Dispatch), and GCD is very easy to use. It assigns tasks to different queue queues for processing. Developers put the task code into a block, the operating system to assign these task code to different resources to deal with, a simple example, why beginners write TableView, when the sliding list is always very card, because many beginners put the picture loaded into main Thread main thread to execute, for example, we want to slide smoothly, iOS fastest can be refreshed in 1 seconds 60 times, how your cell text and pictures loaded more than 1/60 seconds, will naturally card. So generally we will take the picture load these need more time to move out of the main thread to deal with, for GCD, is to put the picture loaded into another queue to execute asynchronously, when the resources are ready, put back to the main thread display. The main thread in GCD is the main queue.
To create a new queue queue code:
dispatch_queue_t Network_queue;
Network_queue = Dispatch_queue_create ("Com.myapp.network", Nill);
For example, our picture reads are put to Network_queue for asynchronous execution
Dispatch_async (Network_queue, ^{
UIImage *cellimage = [self loadmyimagefromnetwork:image_url];
Cache a picture locally
[Self cacheimage:cellimage];
.....
} );
Dispatch_async means asynchronous parallel processing of tasks, which does not necessarily require one task to process the next. The above code loadmyimagefromnetwork means to read the image from the network, this task is given to Network_queue to deal with. This will not block the processing of the main thread interface because it takes too long to read the picture.
When we finish the picture, we should update the interface, from the concept of queue to design, is to put the update interface code into the main queue, because iOS is always the main thread to refresh the redraw UI. So the code should be,
Dispatch_async (Network_queue, ^{
UIImage *cellimage = [self loadmyimagefromnetwork:image_url];
Cache a picture locally
[Self cacheimage:cellimage];
Back to main thread
Dispatch_async (Dispatch_get_main_queue (), ^{
Show image to interface
[Self displayimagetotableview:cellimage];
}];
} );
The Dispatch_get_main_queue () function is to return to the main thread, ^{} encapsulates the task code so that it can be nested from one queue to another, which is as simple as that.
We can generally put networking related code into a queue, the picture resize code to another queue, after processing the update interface, only nested jump back to the main queue. This adds a few lines of code, your program can take advantage of the system multi-core resources, the specific dispatching work to the operating system itself to allocate. With this code, whether your hardware is single-core, dual-core or imac 4-core, or even 8-core, can be handled very well in parallel.
Memory management
I've been amazed by the memory processing capabilities of iOS and objective-c, such as the ipad version of the Iwork,pages app, which is a memory-processing technology application. It's not easy to think of a 256M memory ipad that can bring such a gorgeous interface and get such a smooth user experience. The reason is that iOS has always advocated developers to write optimized code within limited hardware resources, using the least CPU and taking up the least amount of memory. (The following code is for iOS SDK 4.1, which may be different because new SDK 4.2 has new changes to memory usage ...) )
As little as possible in the UIView layer
Usually we like to put a lot of control layers (Uilabel,uibutton,uiview, etc.) together in a large uiview container to display our content, this method is generally possible, but if you want to re-refresh the content of the large-area interface, mostly in the ipad application, This method can lead to excessive memory usage and animation delays (compare cards), such as ScrollView's animation comparison card, or, often, a memory warning. One of the important reasons is that each control, especially the transparent bottom, will be redrawn multiple times (drawrect) too much. The solution is to combine as many controls as possible into a single layer, so that the system will reduce the system call DrawRect, resulting in a performance boost.
A very simple example is that inotes provides handwriting, the user can write different strokes on the ipad screen, the beginning of the design is that the user each write a row, inotes will generate a new transparent bottom uiview to maintain this stroke, the user wrote 10 pen, The system produced 10 UIView, each view size is the entire screen, so that the user's undo operation. This scheme brings serious memory problems, because the system will keep each layer a bitmap graph, a pixel needs 4bit to calculate, a layer is the size of 4x1024x768 ~ 3M, 10 layers is 10x3m = 30M, it is clear that the ipad quickly burst memory warning.
The final scenario for this example is that all the strokes are drawn on the same layer, and inotes can save the point of the stroke for undo operations. The solution is that no matter how many strokes the user draws, the interface redraw requires the same resources.
Show pictures of the best size
Many programmers are lazy, the network took down the picture, directly with Uiimageview to display it to the user, the consequence is that the program needs to keep large-size pictures to memory. The solution should be to reduce the image to the size that needs to be displayed, release the memory of the large image, and then display the screen to the user.
Try to use picture pattern instead of a large picture
For example, many interface designers like to put a large basemap on the interface, but the Basemap is always occupied with memory, the best solution is to design a small pattern diagram, and then use this scheme to display the Basemap.
UIImage *smallimage = [[UIImage alloc] initwithcontentsoffile:path];
Backgroundview.backgroundcolor = [Uicolor colorwithpatternimage:smallimage];
[Smallimage release];
Once the resource is exhausted, release it immediately
The general habit of Objective-c is to release the exhausted resources immediately, because it is the programmer who knows when to run out of a resource. For example, we want to read the larger picture, zoom it out and show it to the interface. When the big picture is finished, it should be released immediately. The code is as follows:
UIImage *fullscreenimage = [[UIImage alloc] initwithcontentoffile:path];
UIImage *smallimage = [self resizeimage:fullscreenimage];
[Fullscreenimage release];
Imageview.image = Smallimage;
A large number of generated auto-release Autorelease objects in the loop can be considered using the Autorelease pool package. code example:
For (UIView *subview in bigview.subviews) {
To automatically dispose of object pools using Autorelease pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; Uiimageview *imageview = (Uiimageview *) Subview;
Subview Processing Code
.......
Destroying an automatically released object
[Pool drain];
}
Automatically frees the object pool to release the temporary objects generated within each loop as soon as they are exhausted
The above comments are my years of experience in writing Ipad/iphone program, in addition IOS4.0 Multi-tasking features released, the program can be transferred into the background to run, the Apple Engineer's opinion is that in the background to run, your application should release the objects can be released, Try to keep it around 16M so that other programs run without the ease of squeezing out your application.
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
In the iphone development process, if you encounter loading big data or involve network communication, you need to do these things in a background thread.
In addition to Nsthread, the iphone offers a set of GCD mechanisms to help developers achieve multithreaded development.
Compared with Nsthread, the GCD is more efficient and easier to develop.
GCD is based on the dispatch queue and block.
1. Block can be simply understood as a task. Block behaves like this in a program:
1 NSString * URL = @ "...";
2
3 ^{
4
5 UIImage * image = [UIImage Imagewithurl:url];
6
7};
As you can see from the previous example, blocks can reference data from an external scope. This is also the difference between a block and a normal function, where the block saves the current execution context.
2. The dispatch queue is a FIFO task queue that can push some blocks into this queue and the system executes the blocks in sequence.
Dispatch_async ()
Three types of dispatch queues are available by default in the system:
A. Main. If a block wants to be completed on the main thread, it can be push into the main dispatch queue.
B. Concurrent. The system automatically creates three dispatch queues with different priority levels. Block is not guaranteed to be executed in strict order.
C. Serial. Manual creation of the user is required to ensure that blocks are executed in strict order of push.
Here is an example of an asynchronous load network image:
1 Uiimageview * ImageView = [[Uiimageview alloc] init];
2
3 Dispatch_async (Dispatch_get_global_queue (dispatch_queue_priority_default, 0), ^{
4
5 UIImage * image =;//network Pull substitution code
6
7 Dispatch_async (Dispatch_get_main_queue (), ^{
8
9 Imageview.image = image; Update ImageView in the main thread
10
11});
12
13});
From the above code can be seen, gcd of the front and rear thread synchronization notification mechanism than Nsthread elegant and convenient many.
For official Apple documentation, please refer to:
IOS block concurrency