This article focuses onIOSOfMulti-core programmingAndMemoryManagement, why? Because iPad 2 is already a dual-core CPU! Although the iPad 1 application is no longer slow, you can use Apple'sMulti-core programmingFramework to write more responsive applications.
Multi-core operations
InIOSIn concurrency programming framework is GCD (Grand Central Dispatch), GCD is very simple to use. It distributes tasks to different queueQueue. The developer installs the task code into blocks, and the operating system distributes the task code to different resources for processing. A simple example shows why when a beginner writes tableview, slide list is always very slow, because many beginners put the image to the main thread for execution. For example, if we want to slide smoothly,IOSIt can be refreshed 60 times in one second at most. If your cell's text and images are loaded for more than 1/60 seconds, they will naturally become stuck.
Therefore, we usually need to remove the image from the main thread for processing. For GCD, it is to load the image into another queue for asynchronous execution, when the resource is ready, it is displayed in main thread. Main thread is the main queue in GCD.
Code for creating a new queue:
- dispatch_queue_t network_queue;
- network_queue = dispatch_queue_create("com.myapp.network", nill);
- dispatch_queue_t network_queue;
- network_queue = dispatch_queue_create("com.myapp.network", nill);
For example, we put the image reading to network_queue for asynchronous execution.
- Dispatch_async (network_queue, ^ {
- UIImage * cellImage = [self loadMyImageFromNetwork: image_url];
- // Cache the image locally
- [Self cacheImage: cellImage];
- .....
- });
- Dispatch_async (network_queue, ^ {
- UIImage * cellImage = [self loadMyImageFromNetwork: image_url];
- // Cache the image locally
- [Self cacheImage: cellImage];
- .....
- });
Dispatch_async refers to Asynchronous Parallel Processing of a task. It does not need to be processed before processing the next task. The above code loadMyImageFromNetwork refers to reading images from the network. This task is handed over to network_queue for processing. In this way, the processing of the main thread interface will not be blocked if the image reading time is too long.
After processing the image, we should update the interface and design it from the queue concept, that is, to put the code of the updated interface into the main queue, because iOS always uses the main thread to refresh the UI. So the code should be,
- Dispatch_async (network_queue, ^ {
- UIImage * cellImage = [self loadMyImageFromNetwork: image_url];
- // Cache the image locally
- [Self cacheImage: cellImage];
- // Return to the main thread
- Dispatch_async (dispatch_get_main_queue (), ^ {
- // Display the image to the interface
- [Self displayImageToTableView: cellImage];
- }];
- });
- Dispatch_async (network_queue, ^ {
- UIImage * cellImage = [self loadMyImageFromNetwork: image_url];
- // Cache the image locally
- [Self cacheImage: cellImage];
- // Return to the main thread
- Dispatch_async (dispatch_get_main_queue (), ^ {
- // Display the image to the interface
- [Self displayImageToTableView: cellImage];
- }];
- });
The dispatch_get_main_queue () function returns the main thread, and the ^ {} encapsulates the task code. In this way, the nesting mode can jump from one queue to another, which is so simple.
Generally, we can put networking-related code into a queue, and put the code of the image resize into another queue. After processing, we update the interface and just need to jump back to the main queue nested. By adding a few lines of code, your program can use the system's multi-core resources and assign the specific scheduling work to the operating system itself. With such code, whether your hardware is single-core, dual-core, iMac 4-core, or even 8-core, it can be processed in parallel very well.
Memory Management
I have been amazed at the memory processing capabilities of iOS and Objective-C, such as the iWork of the iPad version. The Pages application is an amazing work of the memory processing technology application. Think about the M memory iPad, which can bring such a gorgeous interface and get such a smooth user experience, is really not simple. The reason is that iOS has always advocated developers to write the optimal code within limited hardware resources, with the Minimum CPU usage and the minimum memory usage.
The following code applies to iOS SDK 4.1. Because the new SDK 4.2 has a new change to memory usage, it may be different ...)
1. Minimize the number of UIView Layers
We usually like to put many control layers UILabel, UIButton, UIView, etc.) together in a large UIView container to display our content. This method is generally acceptable, however, if you need to refresh the large area interface of the content frequently, most of them occur in iPad applications, this method will lead to excessive memory usage and animation latency comparison cards), for example, scrollview animation comparison card, or, often receive a memory warning. One important reason is that each control, especially the transparent bottom, will redraw drawRect multiple times) too much. The solution is to merge several controls into one layer for display as much as possible, so that the system will reduce the number of calls to drawRect, resulting in performance improvement.
In a simple example, iNotes provides the handwriting function. You can write different strokes on the iPad screen. The initial design is that each stroke is written by the user, iNotes will generate a new transparent UIView to keep this stroke. After you write 10 strokes, the system will produce 10 uiviews. The size of each view is the whole screen, this allows you to perform undo operations. This solution brings serious memory problems, because the system maintains a bitmap for each layer, and a pixel requires 4 bits. The size of a layer is 4x1024x768 ~ 3 M, 10 layers are 10x3 M = 30 M, it is obvious that the iPad soon broke out the memory warning.
The final solution of this example is that all strokes are painted on the same layer, and iNotes can save the points of the strokes for undo operations. This solution is to redraw the same resource on the Interface no matter how many strokes you draw.
2. display images of the optimal size
Many programmers are too lazy to use UIImageView to display images taken from the Internet. The consequence is that the program needs to keep large images in the memory. The solution should be to first reduce the image size to be displayed, release the memory size of the large image, and then display it to the user interface.
3. Try to use the image pattern instead of a large image.
For example, many interface designers like to place a large basemap on the interface, but this basemap is always occupying memory. The best solution is to design a small pattern, then, use this scheme to display it as a basemap.
- UIImage *smallImage = [[UIImage alloc] initWithContentsOfFile:path];
- backgroundView.backgroundColor = [UIColor colorWithPatternImage:smallImage];
- [smallImage release];
- UIImage *smallImage = [[UIImage alloc] initWithContentsOfFile:path];
- backgroundView.backgroundColor = [UIColor colorWithPatternImage:smallImage];
- [smallImage release];
4. release resources immediately after they are used
In general, the habit of objective-c is to release the used resources immediately, because it is the programmer who knows when to use a resource.
For example, we want to read a large image, narrow it down, and display it on the interface. Release the large image immediately after it is used. The Code is as follows:
- UIImage *fullscreenImage = [[UIImage alloc] initWithContentOfFile:path];
- UIImage *smallImage = [self resizeImage:fullscreenImage];
- [fullscreenImage release];
- imageView.image = smallImage;
- ......
- UIImage *fullscreenImage = [[UIImage alloc] initWithContentOfFile:path];
- UIImage *smallImage = [self resizeImage:fullscreenImage];
- [fullscreenImage release];
- imageView.image = smallImage;
......
5. The autorelease object is automatically released in a large number of cycles. You can consider using autorelease pool encapsulation.
Sample Code:
- For (UIView * subview in bigView. subviews ){
- // Use autorelease pool to automatically release the object pool
- NSAID utoreleasepool * pool = [[NSAID utoreleasepool alloc] init];
- UIImageView * imageView = (UIImageView *) subview;
- // Subview processing code
- .......
- // Destroy the automatically released object
- [Pool drain];
- }
- For (UIView * subview in bigView. subviews ){
- // Use autorelease pool to automatically release the object pool
- NSAID utoreleasepool * pool = [[NSAID utoreleasepool alloc] init];
- UIImageView * imageView = (UIImageView *) subview;
- // Subview processing code
- .......
- // Destroy the automatically released object
- [Pool drain];
- }
The automatic release Object pool releases the temporary objects generated in each cycle immediately after they are used.
The above comments are my years of experience in writing iPad/iPhone applications.IOSAfter the multi-tasking feature of 4.0 is released, the program can be transferred to the background for running. Apple engineers suggested that when you enter the background for running, your application should release objects that can be released, keep it at around 16 MB, so that other programs cannot easily squeeze out your applications.
Summary:IOSApplication in progressMulti-core programmingAndMemoryI hope this article will help you with the management!