`
啸笑天
  • 浏览: 3482728 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

25 iOS App Performance Tips & Tricks

 
阅读更多

from http://www.raywenderlich.com/31166/25-ios-app-performance-tips-tricks

 

This is a post by iOS Tutorial Team Member Marcelo Fabri, an iOS developer working at Movile. Check out his personal websiteor follow him on Twitter.

When developing an iOS app, it’s critical that your app has good performance. Your users expect it, and it will hurt your reviews if your app appears unresponsive or slow.

However, due to the limitations of iOS devices this can sometimes be quite hard to get working quite right. There’s a lot to keep in mind during development, and it’s easy to forget the performance impact of your decisions.

That is exactly why I wrote this article! This article gathers together 25 tips and tricks that you can use to improve the performance of your apps, in the form of a handy checklist.

So keep reading to give your future apps a nice boost!

Note: Before optimizing any code, make sure there’s a problem to be solved! Don’t get sucked into the mistake of “pre-optimizing” your code. Use Instruments frequently to profile your code and uncover any areas that need improvement. Matt Galloway wrote a great tutorial about using Instruments to optimize your code.

Also, keep in mind that some of the tips offered in this article offered are trade-offs; the suggested improvements will make your code faster or more efficient, but they may require a lot of work to implement, or make your code more complicated, so choose wisely!

 

Table of Contents

The tips below are categorized into three different levels – beginner, intermediate and advanced:

Beginner

These are tips that you’ll always want to implement in any app you develop.

  1. Use ARC to Manage Memory
  2. Use a reuseIdentifier Where Appropriate
  3. Set Views as Opaque When Possible
  4. Avoid Fat XIBs
  5. Don’t Block the Main Thread
  6. Size Images to Image Views
  7. Choose the Correct Collection
  8. Enable GZIP Compression

Intermediate

These are tips you should use when you run into slightly more complicated issues.

  1. Reuse and Lazy Load Views
  2. Cache, Cache, Cache
  3. Consider Drawing
  4. Handle Memory Warnings
  5. Reuse Expensive Objects
  6. Use Sprite Sheets
  7. Avoid Re-Processing Data
  8. Choose the Right Data Format
  9. Set Background Images Appropriately
  10. Reduce Your Web Footprint
  11. Set the Shadow Path
  12. Optimize Your Table Views
  13. Choose Correct Data Storage Option

Advanced

These are tips you should use only when you’re positive they’ll fix the issue, and you feel comfortable using them.

  1. Speed up Launch Time
  2. Use Autorelease Pool
  3. Cache Images – Or Not
  4. Avoid Date Formatters Where Possible

Without further ado, let’s get into the tips!

Beginner Performance Improvements

This section is dedicated to basic changes that can improve your app’s performance. But developers of all levels will still benefit from this quick checklist of items that are still sometimes overlooked.

 
1) Use ARC to Manage Memory

ARC was released with iOS 5 and it eliminates the most common kind of memory leaks – the forgetful ones.

ARC stands for “Automatic Reference Counting”, and it automatically manages the retain/release cycles in your code, so you don’t have to do it manually.

The code block below shows some common code that you might use to create a view:

UIView *view = [[UIView alloc] init];
// ...
[self.view addSubview:view];
[view release];

It’s tremendously easy to forget the release call at the end of this code block. ARC does it for you, automatically and under-the-hood.

In addition to helping you avoid memory leaks, ARC can also improve your performance, by making sure that objects are deallocated as soon as they are no longer needed. These days, you should always use ARC in your projects!

Here are a few great resources to learn more about ARC:

It’s worth noting that ARC doesn’t eliminate all memory leaks. You can still have memory leaks, but they’ll mainly be due to blocks, retain cycles, poorly managed CoreFoundation objects (and C structures in general), or just really poorly written code.

There’s a very good blog post that details some of the issues that ARC can’t fix — and how to deal with them.

 
2) Use a reuseIdentifier Where Appropriate



 

Use a reuseIdentifier Where Appropriate.

A common mistake in app development is not setting the correct reuseIdentifier for UITableViewCells, for UICollectionViewCells, or even UITableViewHeaderFooterViews.

For maximum performance, a table view’€™s data source should generally reuse UITableViewCell objects when it assigns cells to rows in tableView:cellForRowAtIndexPath:. A table view maintains a queue or list of UITableViewCell objects that the data source has marked for reuse.

What happens if you don’t use a reuseIdentifier?

If you don’t, your table view will configure a brand-new cell each time a row is displayed. This is an expensive operation and will definitely affect the scrolling performance of your app.

Since the introduction of iOS 6, you’re expected to use reuseIdentifiers for header and footer views, as well as UICollectionView’s cells and supplementary views.

To use reuseIdentifiers, call this method from your data source object when asked to provide a new cell for the table view:

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

This method dequeues an existing cell if one is available, or creates a new one if necessary using the previously registered nib file or class. If no cell is available for reuse, and you did not register a class or nib file, this method returns nil.

 
3) Set Views as Opaque When Possible



 

Set Views as Opaque When Possible.

If you have opaque views — that is, views that have no transparency defined — you should set their opaque property to YES.

Why? This will allow the system to draw your views in an optimal manner. It’s a simple property that can be set in both Interface Builder and code.

The Apple documentation has this to say about setting the opaque property for images:

This property provides a hint to the drawing system as to how it should treat the view. If set to YES, the drawing system treats the view as fully opaque, which allows the drawing system to optimize some drawing operations and improve performance. If set to NO, the drawing system composites the view normally with other content. The default value of this property is YES.

On relatively static screens, setting the opaque property won’t be a big deal. However, if your view is embedded in a scroll view, or is part of a complex animation, not setting this property will definitely impact the performance of your app!

You can also use the Debug\Color Blended Layers option in the simulator to see visually what views are not set as opaque. Your goal should be to make as many of your views opaque as possible!

 
4) Avoid Fat XIBs



 

Avoid Fat XIBs.

Storyboards, introduced in iOS 5, are quickly replacing XIBs. However, XIBs are still useful in some cases. If you need to target pre-iOS 5 devices, or you have a custom reusable view, then you can’t really avoid them.

If you’re forced into using XIBs, make them as uncomplicated as possible. Try to create one XIB per view controller, and if possible, break out a view controller’s view hierarchy into separate XIBs.

Note that when you load a XIB into memory, all of its contents are loaded into memory, including any images. If you have a view you’re not using immediately, then you’re wasting precious memory. It’s worth noting that this won’t happen with storyboards, since a storyboard will only instantiate a view controller when it’s needed.

When you load a XIB, any image files are cached, along with sound files if you’re developing for OS X.Apple’s documentation has this to say:

When you load a nib file that contains references to image or sound resources, the nib-loading code reads the actual image or sound file into memory and and caches it. In OS X, image and sound resources are stored in named caches so that you can access them later if needed. In iOS, only image resources are stored in named caches. To access images, you use the imageNamed: method of NSImage or UIImage, depending on your platform.

Apparently, this also happens when using storyboards; however, I wasn’t able to find anything supporting this claim. If you know anything about this behavior, please drop me a line!

Want to learn more about storyboards? Check out Matthijs Hollemans’ Beginning Storyboards in iOS 5 Part 1and Part 2.

 
5) Don’t Block the Main Thread



 

Don’t Block the Main Thread.

You should never do any heavy lifting on the main thread. This is because UIKit does all of its own work on the main thread, such as drawing, managing touches, and responding to input.

The risk of doing all of your app’s work on the main thread is that if your code does block this thread, your app will appear unresponsive. That’s a quick route to one-star reviews on the App Store! :]

Most cases of blocking the main thread occur when your app is performing an I/O operation which involves any task that needs to read or write from an external source, such as the disk or the network.

You can perform network tasks asynchronously by using this method on NSURLConnection:

+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler

or by using a third party framework such as AFNetworking.

If you’re doing any other kind of expensive operation (such as performing a time-intensive computation or reading/writing to the disk) then use Grand Central Dispatch, or NSOperations and NSOperationQueues.

The template for using GCD looks like the code below:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // switch to a background thread and perform your expensive operation
 
    dispatch_async(dispatch_get_main_queue(), ^{
        // switch back to the main thread to update your UI
 
    });
});

See how there’s a nested dispatch_async inside the first one? That’s because any UIKit related code needs to be executed on the main thread.

Curious about the finer details of NSOperation or GCD? Take a look at Ray Wenderlich’s Multithreading and Grand Central Dispatch on iOS for Beginners tutorial, as well as Soheil Azarpour’s How To Use NSOperations and NSOperationQueues tutorial.

 
6) Size Images to Image Views



 

Size Images to Image Views.

If you’re displaying an image from the app’s bundle in a UIImageView, make sure that the image and the UIImageView are same size. Scaling images on the fly can be expensive, especially if your UIImageView is embedded in a UIScrollView.

If the image is downloaded from a remote service, sometimes you don’t have control over the size, or you might not be able to scale it on the server prior to downloading. In cases like these, you can scale the image manually once you’ve finish downloading it — preferably on a background thread! — and then use the resized image in your UIImageView.

 
7) Choose the Correct Collection



 

Choose the Correct Collection.

Learning to use the most appropriate class or object for the task at hand is fundamental to writing efficient code. This is especially true when dealing with collections.

Happily, there’s a document named Collections Programming Topics on Apple’s Developer Library that explains in detail the differences between the available classes, as well as which situations suit each class. It’s a must read document for anyone looking to work with collections.

TLDR? Here’s a quick synopsis of the most common collection types:

  • Arrays: Ordered list of values. Quick lookup by index, slow to lookup by value, slow to insert/delete.
  • Dictionaries: Store key/value pairs. Quick lookups by key.
  • Sets: Unordered list of values. Quick lookup by value, quick to insert/delete.

 

8) Enable GZIP Compression



 

Enable GZIP compression.

A significant and growing number of apps rely on external data from remote servers or other external APIs. At some point you’ll be developing an app that downloads data in XML, JSON, HTML or some other text format.

The problem is that the network condition cannot be relied upon when it comes to mobile devices. A user can be on an EDGE network one minute, and the a 3G network the next. Whatever the scenario, you don’t want to keep your user waiting!

One option to reduce the file size and speed up the download of network-based resources is by enabling GZIP compression on both your server and on your client. This is especially useful for text-based data, which has a high potential ratio for compression.

The good news is that iOS already supports GZIP compression by default if you’re using NSURLConnection, or a framework built on top of it such as AFNetworking. Even more good news is that some cloud providers, such as Google App Engine already send compressed responses.

There’s a great article about GZIP compression which explains how to enable it on your Apache or IIS server.

Intermediate Performance Improvements

Okay, so you’re pretty confident that you’ve hit all of the low-hanging fruit when it comes to optimizing your code. But sometimes there are solutions that aren’t quite as obvious, and depend heavily on how you structure and code your app. However, in the right context, they can be invaluable!

 
9) Reuse and Lazy Load Views

More views means more drawing; which ultimately means more CPU and memory overhead. This is especially true if your app embeds many views inside of a UIScrollView.

The trick to managing this is to mimic the behavior of UITableView and UICollectionView: don’t create all subviews at once. Instead, create your views as you need them, adding them to a reuse queue when you’re finished with them.

This way, you have only to configure your views when a scroll is performed, avoiding the allocation cost — which can be expensive.

The problem of timing the creation of views applies to other areas of your app as well. Take the situation where you need to present a view when the user taps a button. There are at least two approaches to this:

  1. Create the view when the screen is first loaded and hide it; then when you need it, show it.
  2. Do nothing until you need to show the view. Then, create the view and show it, all at once.

Each approach has its own pros and cons.

Using the first method, you consume more memory because you immediately create the view which holds on to that memory until it’s released. However, when the user does taps the button, your app will appear more responsive as it only needs to change the view’s visibility.

Taking the second approach will have the opposite effect; by creating the view only when it’s required, you consume less memory; however, the app won’t appear as responsive when the button is tapped.

 
10) Cache, Cache, Cache

A great rule of thumb when developing your app is to “cache what matters” — that is, things that are unlikely to change, but are accessed frequently.

What can you cache? Some candidates for caching are remote server responses, images, or even calculated values, such as UITableView row heights.

NSURLConnection already caches resources on disk or in memory according to the HTTP headers it processes. You can even create a NSURLRequest manually and make it load only cached values.

Here’s a great snippet to use whenever you need to create a NSURLRequest for an image that is unlikely to change:

+ (NSMutableURLRequest *)imageRequestWithURL:(NSURL *)url {
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
 
    request.cachePolicy = NSURLRequestReturnCacheDataElseLoad; // this will make sure the request always returns the cached image
    request.HTTPShouldHandleCookies = NO;
    request.HTTPShouldUsePipelining = YES;
    [request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
 
    return request;
}

Note that you can fetch a URL request via NSURLConnection, but AFNetworking can fetch it as well; that way you don’t need to change all your networking code because of this tip! :]

If want to know more about HTTP caching, NSURLCache, NSURLConnection and friends, be sure to take a look at the NSURLCache entry on NSHipster.

If you need to cache other things that don’t involve HTTP requests, then NSCache is your go-to guy.

NSCache looks and behaves like an NSDictionary, but it automatically removes its contents when the system needs to reclaim memory. Mattt Thompson wrote this amazing post on NSHipster about it.

Interested in learning more about HTTP caching? Google has a best-practices document on HTTP cachingthat is a recommended read.

 
11) Consider Drawing



 

Consider Drawing.

There are several ways to make great-looking buttons in iOS. You can use full sized images, resizable images, or you could go the distance and draw it manually using CALayer, CoreGraphics or even OpenGL.

Of course, there’s different levels of complexity with each of these approaches, as well as differences in their performance. There’s an awesome post about iOS graphics performance herewhich is well worth a read. Andy Matuschak, who is a member of the UIKit team over at Apple, commented on the post, and there’s some great insight into the different approaches and their performance trade-offs.

The short story is that using pre-rendered images is faster, because iOS doesn’t have to create an image and draw shapes on it to finally draw into than screen (the image is already created!). The problem is that you need to put all those images in your app’s bundle, increasing its size. That’s why using resizable images is so great: you save space by removing “wasted” image space that iOS can repeat for you. You also don’t need to generate different images for different elements (e.g. buttons).

However, by using images you lose the ability to tweak your images by code, needing to regenerate them every and putting them into the app again and again. That can be a slow process. Another point is that if you have an animation or just a lot of images with slightly changes (they can have multiple overlay color, for example), you’ll have to embed a lot of images, growing the app’s bundle size.

To summarize, you need to think what’s most important to you: drawing performance or app’s size. Generally both are important, so you’ll use both approaches in the same project!

 
12) Handle Memory Warnings

iOS notifies all running apps when system memory is running low. Here’s what the official Apple documentation says about handling the low memory warning:

If your app receives this warning, it must free up as much memory as possible. The best way to do this is to remove strong references to caches, image objects, and other data objects that can be recreated later.

Fortunately, UIKit provides several ways to receive these low-memory warnings, including the following:

  • Implement the applicationDidReceiveMemoryWarning: method of your app delegate.
  • Override didReceiveMemoryWarning in your custom UIViewController subclass.
  • Register to receive the UIApplicationDidReceiveMemoryWarningNotification notification.

Upon receiving any of these warnings, your handler method should respond by immediately freeing up any unnecessary memory.

For example, the default behavior of UIViewController is to purge its view if that view is not currently visible; subclasses can supplement the default behavior of their parent class by purging additional data structures. An app that maintains a cache of images might respond by releasing any images that are not currently on-screen.

It’s very important to release all memory possible once you receive a memory warning. Otherwise, you run the risk of having your app killed by the system.

However, be careful when you start culling objects to free up memory, as you’ll need to make sure they can be recreated later. Be sure to use the Simulate memory warning feature on the iOS simulator to test this condition while you are developing your app!

 
13) Reuse Expensive Objects



 

Some objects are very slow to initialize — NSDateFormatter and NSCalendar are two examples. However, you can’t always avoid using them, such as when parsing dates from a JSON/XML response.

To avoid performance bottlenecks when working with these objects, try to reuse these objects if at all possible. You can do this by either adding a property to your class, or by creating a static variable.

Note that if you choose the second approach, the object will remain in memory while your app is running, much like a singleton.

The code below demonstrates making a property that lazy-loads a date formatter. The first time it is called, it creates a new date formatter. Future calls will just return the already created instance:

// in your .h or inside a class extension
@property (nonatomic, strong) NSDateFormatter *formatter;
 
// inside the implementation (.m)
// When you need, just use self.formatter
- (NSDateFormatter *)formatter {
    if (! _formatter) {
        _formatter = [[NSDateFormatter alloc] init];
        _formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy"; // twitter date format
    }
    return _formatter;
}

Also remember that setting a NSDateFormatter’s date format is almost as slow as creating a new one! Therefore, if you frequently need to deal with multiple date formats in your app, your code may benefit from initially creating, and reusing, multiple NSDateFormatter objects.

 
14) Use Sprite Sheets



 

Use sprite sheets.

So you’re a game developer? Then sprite sheets are one of your best friends. Sprite sheets make drawing faster and can even consume less memory than standard screen drawing methods.

There are two awesome sprite sheet tutorials about sprite sheets on this site:

  1. How To Use Animations and Sprite Sheets in Cocos2D
  2. How to Create and Optimize Sprite Sheets in Cocos2D with Texture Packer and Pixel Formats

The second tutorial covers pixel formats in detail, which can have a measurable impact on a game’s performance.

If you’re not yet familar with sprite sheets, then a great introduction can be found in SpriteSheets – The Movie, Part 1and Part 2. The author of these videos is Andreas Löw, the creator of Texture Packer, one of the most popular tools for creating sprite sheets.

Besides using sprite sheets, several tips already covered here can be applied to games as well. For example, if your game has many sprites, such as enemies or projectiles in your standard shoot-em-up, then you can reuse sprites instead of recreating them every time.

 
15) Avoid Re-Processing Data

Many apps make calls for data from remote servers to get information the app requires to function. This data usually comes across in JSON or XML format. It’s important to try and use the same data structure at both ends when requesting and receiving the data.

Why? Manipulating data in memory to fit your data structures can be expensive.

For example, if you need to display the data in a table view, it would be best to request and receive the data in an array format to avoid any intermediate manipulation of the data to make it fit the data structure that you’re using in your app.

Similarly, if your application depends on accessing specific values by their keys, then you’ll probably want to request and receive a key/value pair dictionary.

By getting the data in the right format the first time, you’ll avoid a lot of re-processing in your app to make the data fit your chosen structure.

 
16) Choose the Right Data Format



 

Choose the right data format.

There are multiple ways you can transfer data to your app from a web service, but the most common two are JSON and XML. You want to make sure you choose the right one for your app.

JSON is faster to parse, and is generally smaller than XML, which means less data to transfer. And since iOS 5, there’s built-in JSON deserialization so it’s easy to use as well.

However, one advantage XML has is that if you use the SAXparsing method, you can work with XML data as you read it off the wire, instead of having to wait for the entire data to arrive before you parse it like JSON. This can give you increased performance and reduced memory consumption when you are dealing with very large sets of data.

 

17) Set Background Images Appropriately

Like many other things in iOS coding, there’s at least two different ways to place a background image on your view:

  1. You can set your view’s background color to a color created with UIColor’s colorWithPatternImage.
  2. You can add a UIImageView subview to the view.

If you have a full size background image, then you should definitely use a UIImageView because UIColor’s colorWithPatternImage was made to create small pattern images that will be repeated, and not large images size. Using UIImageView will save a lot of memory in this case.

// You could also achieve the same result in Interface Builder
UIImageView *backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background"]];
[self.view addSubview:backgroundView];

However, if you plan to have a patterned image background, which uses smaller images which will be repeated or tiled to fill the background, you should go with UIColor’s colorWithPatternImage instead, as it’s faster to draw and won’t use a lot of memory in this case.

self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background"]];

 
18) Reduce Your Web Footprint

UIWebView is very useful. It’s a very easy to display web content, or even to create a visual aspect of your app that would be difficult with standard UIKit controls.

However, you may notice that the UIWebView component you can use in your apps is not as fast as the one which powers Apple’s Safari app. This is down to the restricted use of Webkit’s Nitro Engine, which featuresJIT compilation.

So to get the best performance, you’ll need to tweak your HTML a bit. The first thing you should do is get rid of as much Javascript as you can, which includes avoiding large frameworks such as jQuery. It can sometimes be a lot faster to work with vanilla Javascript instead of relying on frameworks to do the work for you.

Also follow the practice of loading your Javascript files asynchronously where possible – especially when they don’t directly impact the behavior of the page, such as analytics scripts.

And finally — always be aware of the images that you are using, and keep images right-sized for your purposes. As mentioned earlier in this tutorial, make use of sprite sheets wherever possible to conserve memory and improve speed.

For more information, be sure to take a look at WWDC 2012 session #601 – Optimizing Web Content in UIWebViews and Websites on iOS.

 
19) Set the Shadow Path

So you need to add a shadow to a view, or to a layer. How should you handle this?

Most developers would just add the QuartzCore framework to their project, and then add the following code:

#import <QuartzCore/QuartzCore.h>
 
// Somewhere later ...
UIView *view = [[UIView alloc] init];
 
// Setup the shadow ...
view.layer.shadowOffset = CGSizeMake(-1.0f, 1.0f);
view.layer.shadowRadius = 5.0f;
view.layer.shadowOpacity = 0.6;

Looks pretty easy, right?

The bad news is that there’s a problem with this approach. Core Animation has to do an offscreen pass to first determine the exact shape of your view before it can render the drop shadow, which is a fairly expensive operation.

The good news is that there’s an alternative that is much easier for the system to render: setting the shadow path!

view.layer.shadowPath = [[UIBezierPath bezierPathWithRect:view.bounds] CGPath];

By setting the shadow path, iOS won’t need to recalculate how it should draw the shadow all the time. Instead it’s going to use a pre-calculated path that you’re informing. The bad news is that depending on your view format, it may be harder to calculate the path by your own. Another problem is that you need to update the shadow path every time your view’s frame changes.

If you want to know more about this trick, Mark Pospesel wrote a great post about shadowPath.

 
20) Optimize Your Table Views

Table views need to scroll quickly — when they don’t, users really notice the lag.

To keep your table views scrolling smoothly, ensure that you’ve implemented all of the suggestions below:

  • Reuse cells by setting the correct reuseIdentifier.
  • Make as many views opaque as possible, including the cell itself.
  • Avoid gradients, image scaling, and offscreen drawing.
  • Cache the height of any rows if they aren’t always the same.
  • If the cell shows content that comes from the web, be sure to make those calls asynchronously and cache the responses.
  • Use shadowPath to set up shadows.
  • Reduce the number of subviews.
  • Do as little work as possible in cellForRowAtIndexPath:. If you need to do some work, do it only once and cache the results.
  • Use the appropriate data structure to hold the information you need. Different structures have different costs for different operations.
  • Use rowHeight, sectionFooterHeight and sectionHeaderHeight to set constant heights instead of asking the delegate.

 
21) Choose Correct Data Storage Option



 

Choose Correct Data Storage Option.

What are your options when it comes to storing and reading large data sets?

You have several options, including:

  • Store them using NSUserDefaults
  • Save to a structured file in XML, JSON, or Plist format
  • Archive using NSCoding
  • Save to a local SQL database such as SQLite
  • Use Core Data.

What’s the issue with NSUserDefaults? Although NSUserDefaults is nice and easy, it’s really only good if you have a very small amount of data to save (like what level you’re on, or whether sound is turned on and off). Once you start getting large amounts of data, other options are better.

Saving to a structured file can be problematic as well. Generally, you need to load the entire file into memory before you can parse it, which is an expensive operation. You could use SAX to process a XML file, but that’s a complex solution. As well, you’d end up having all objects loaded in memory — whether you want them there or not.

Okay, then, what about NSCoding? Unfortunately, it also reads and writes to a file, so it experiences the same problems as above.

Your best bet in this situation is to use SQLite or Core Data. By using these technologies, you can perform specific queries to only load the objects you need and avoid a brute-force searching approach to retrieve the data. In terms of performance, SQLite and Core Data are very similar.

The big difference between SQLite and Core Data is really about the general usage of each. Core Data represents an object graph model, while SQLite is just a regular DBMS. Usually Apple recommends that you go with Core Data, but if you have a particular reason you want to avoid it, you can go lower level to SQLite.

If you choose to use SQLite in your app, a handy library to use is FMDB which allows you to work with a SQLite database without having to delve into the SQLite C API.

Advanced Performance Tips

Looking for some elite ways to become a total code ninja? These advanced performance tips can be used when appropriate to make your apps run as efficiently as possible!

 
22) Speed up Launch Time

Launching your app quickly is very important, especially when the user launches for the first time. First impressions mean a lot for an app!

The biggest thing that you can do to ensure your app starts as quickly as possible is to perform as many asynchronous tasks as possible, such as network requests, database access, or parsing data.

As well, try to avoid fat XIBs, since they’re loaded on the main thread. But recall that storyboards don’t have this problem — so use them if you can!

Note: The watchdog doesn’t run while debugging with Xcode, so be sure to test your app with your device disconnected from Xcode while testing for launch performance.

 
23) Use Autorelease Pool

NSAutoreleasePool is responsible for releasing the autoreleased objects within a block. Usually, it’s called automatically by UIKit. But there are some scenarios where may you need to create NSAutoreleasePools manually.

For example, if you create a lot of temporary objects in your code, you’ll note that memory usage increases until these objects are released. The problem is that this memory is only released after UIKit drains its autorelease pool, which means this memory is held much longer than necessary.

The good news is that you can avoid this by creating these temporary objects inside your own @autoreleasepool block, as shown in the code below:

NSArray *urls = <# An array of file URLs #>;
for (NSURL *url in urls) {
    @autoreleasepool {
        NSError *error;
        NSString *fileContents = [NSString stringWithContentsOfURL:url
                                         encoding:NSUTF8StringEncoding error:&error];
        /* Process the string, creating and autoreleasing more objects. */
    }
}

This releases all the autorelease objects at the end of each iteration.

You can read more about NSAutoreleasePool in Apple’s official documentation.

 
24) Cache Images – Or Not

There are two common ways to load a UIImage from an app bundle. The first, and more common way to do it is using imageNamed. The second, and less common way, is with imageWithContentsOfFile.

Why are there two methods which effectively achieve the same thing?

imageNamed has the advantage of caching the image as it’s loaded. The documentation for imageNamedexplains it this way:

This method looks in the system caches for an image object with the specified name and returns that object if it exists. If a matching image object is not already in the cache, this method loads the image data from the specified file, caches it, and then returns the resulting object.

Alternately, imageWithContentsOfFile simply loads the image with no caching.

The two methods are demonstrated in the code block below:

UIImage *img = [UIImage imageNamed:@"myImage"]; // caching
// or
UIImage *img = [UIImage imageWithContentsOfFile:@"myImage"]; // no caching

When would you use one over the other?

If you’re loading a large image that will be used only once, there’s no need to cache the image. In this caseimageWithContentsOfFile will fit the bill nicely – this way, the OS doesn’t waste memory caching the image.

However, imageNamed is a much better choice for images that you’re going to be reusing in your app. This way, the OS saves time having to constantly load the image from disk.

 
25) Avoid Date Formatters Where Possible

If you have a lot of dates that you need to parse with NSDateFormatter, you need to tread carefully. As mentioned previously, it’s always a good idea to reuse NSDateFormatters whenever possible.

However, if you need more speed, you can parse dates directly using C instead of NSDateFormatter. Sam Soffes wrote a blog post about this topic which presents some code to parse ISO-8601 date strings. However, you can easily tweak his code examples to fit your particular needs.

Well, that sounds great — but would you believe there’s an even better way?

If you can control the format of the dates you are dealing with, choose Unix timestamps if at all possible. Unix timestamps are simply integers which represent how many seconds have passed since the “epoch”, which is simply the common reference date of 00:00:00 UTC on 1 January 1970.

You can easily transform this timestamp into an NSDate, as shown below:

 
- (NSDate*)dateFromUnixTimestamp:(NSTimeInterval)timestamp {
    return [NSDate dateWithTimeIntervalSince1970:timestamp];
}

This is even faster than the C function!

Note that many web APIs return timestamps as milliseconds, since it’s very common for Javascript to eventually consume and process this data. Just be aware that you’ll need to divide the timestamp by 1000 before passing it to the dateFromUnixTimestamp method.

Where to Go From Here?

The following WWDC videos are highly recommended viewing for anyone interested in optimizing the performance of their apps. You’ll first need to ensure that you’ve registered your Apple ID as a developer, but once that’s done, you can have your fill of any of the videos from WWDC 2012:

  • #406: Adopting Automatic Reference Counting
  • #238: iOS App Performance: Graphics and Animations
  • #242: iOS App Performance: Memory
  • #235: iOS App Performance: Responsiveness
  • #409: Learning Instruments
  • #706: Networking Best Practices
  • #514: OpenGL ES Tools and Techniques
  • #506: Optimizing 2D Graphics and Animation Performance
  • #601: Optimizing Web Content in UIWebViews and Websites on iOS
  • #225: Up and Running: Making a Great Impression with Every Launch

There’s also some videos from WWDC 2011 that contain some great information as well:

  • #308: Blocks and Grand Central Dispatch in Practice
  • #323: Introducing Automatic Reference Counting
  • #312: iOS Performance and Power Optimization with Instruments
  • #105: Polishing Your App: Tips and tricks to improve the responsiveness and performance
  • #121: Understanding UIKit Rendering

There’s even more videos, mostly from iOS 5 Tech Talks:

  • Your iOS App Performance Hitlist
  • Optimizing App Performance with Instruments
  • Understanding iOS View Compositing

Based on “Your iOS App Performance Hitlist” video there’s a post written by Ole Begemann, that is a textual summary about the original presentation by Michael Jurewitz.

Apple has also provided a very useful resource called Performance Tuning, which provides a lot of great additional tips and tricks about making your apps perform well on iOS.

I hope you found this collection of tips helpful. If you know of a good tip that isn’t mention here, or have any comments or questions, please join the forum discussion below!

  • 大小: 13.1 KB
  • 大小: 33.1 KB
  • 大小: 44.5 KB
  • 大小: 30.5 KB
  • 大小: 7.6 KB
  • 大小: 62.4 KB
  • 大小: 37.7 KB
  • 大小: 18.6 KB
  • 大小: 13.2 KB
  • 大小: 19.6 KB
  • 大小: 11.6 KB
  • 大小: 53.5 KB
分享到:
评论
5 楼 啸笑天 2013-04-28  
5) 不要阻塞主线程

永远都不要在主线程做繁重的任务。因为UIKit的左右任务都在主线程中进行,例如绘制、触摸管理和输入响应。

在主线程做所有任务的风险是:如果你的代码阻塞了主线程,那么程序将出现反应迟钝。这回招致用户在App Store上对程序的差评!

在执行I/O操作中,大多数情况下都会祖塞主线程,这些操作需要从读写外部资源,例如磁盘或者网络。

关于网络操作可以使用NSURLConnection的如下方法,以异步的方式来执行:
1.+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler
或者使用第三方框架,例如AFNetworking。

如果你需要做一些其它类型开销很大的操作(例如执行一个时间密集型的计算或者对磁盘进行读写),那么就使用GCD(Grand Central Dispatch),或NSOperations 和 NSOperationQueues。

下面的代码是使用GCD的一个模板:
1.dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
2.    // switch to a background thread and perform your expensive operation
3.
4.    dispatch_async(dispatch_get_main_queue(), ^{
5.        // switch back to the main thread to update your UI
6.
7.    });
8.});
如上代码,为什么在第一个dispatch_async里面还嵌套了一个dispatch_async呢?这是因为关于UIKit相关的代码需要在主线程里面执行。
可以看看Ray Wenderlich中的教程:iOS中多线程和GCD—初级,以及Soheil Azarpour的如何使用NSOperations和NSOperationQueues教程。
4 楼 啸笑天 2013-04-28  
4) 避免臃肿的XIBs

避免臃肿的XIBs

在iOS 5中开始使用Storyboards,并且将替代XIBs。不过在有些情况下XIBs仍然有用。如果你的程序需要运行在装有iOS 5之前版本的设备上,或者要自定义可重用的view,那么是避免不了要使用XIBs的。

如果必须要使用XIBs的话,尽量让XIBs文件简单。并且每个view controller对于一个XIB文件,如果可以的话,把一个view controller的view不同的层次单独分到一个XIBs文件中。

(注意:当把一个XIB文件加载到内存时,XIB文件中的所有内容都将被加载到内存中,包括图片。如果有一个view还不立即使用的话,就会造成内存的浪费。而这在storyboard中是不会发生的,因为storyboard还在需要的时候才实例化一个view controller。)

当加载XIB时,所有涉及到的图片都将被缓存,并且如果是开发的程序是针对OS X的话,声音文件也会被加载。苹果的官方文档这样说:
When you load a nib file that contains references to image or sound resources, the nib-loading code reads the actual image or sound file into memory and and caches it. In OS X, image and sound resources are stored in named caches so that you can access them later if needed. In iOS, only image resources are stored in named caches. To access images, you use the imageNamed: method of NSImage or UIImage, depending on your platform.
(当加载一个nib文件时,也会将nib文件涉及到的图片或声音资源加载到内存中,nib-loading代码会将实际的图片或声音文件读取到内存中,并一直缓存着。在OS X中,图片和声音资源都存储在命名缓存中,这样之后如果需要的话,可以对其进行访问。在iOS中,只有图片资源被存储到命名缓存中。要访问图片的话,使用NSImage或UIImage(根据不同的系统)的imageNamed:方法即可。)

显然,在使用storyboard时也会发生类似的缓存操作;不过我没有找到相关内容的任何资料。想要学习storyboard的更多知识吗?可以看看Matthijs Hollemans写的iOS 5中:初级Storyboard Part 1和Part2。
3 楼 啸笑天 2013-04-28  
3) 尽可能将View设置为不透明(Opaque)

尽量将view设置为Opaque

如果view是不透明的,那么应该将其opaque属性设置为YES。为什么要这样做呢?这样设置可以让系统以最优的方式来绘制view。opaque属性可以在Interface Builder或代码中设置。

苹果的官方文档对opaque属性有如下解释:
This property provides a hint to the drawing system as to how it should treat the view. If set to YES, the drawing system treats the view as fully opaque, which allows the drawing system to optimize some drawing operations and improve performance. If set to NO, the drawing system composites the view normally with other content. The default value of this property is YES.
(opaque属性提示绘制系统如何处理view。如果opaque设置为YES,绘图系统会将view看为完全不透明,这样绘图系统就可以优化一些绘制操作以提升性能。如果设置为NO,那么绘图系统结合其它内容来处理view。默认情况下,这个属性是YES。)

如果屏幕是静止的,那么这个opaque属性的设置与否不是一个大问题。但是,如果view是嵌入到scroll view中的,或者是复杂动画的一部分,不将设置这个属性的话肯定会影响程序的性能!可以通过模拟器的Debug\Color Blended Layers选项来查看哪些view没有设置为不透明。为了程序的性能,尽可能的将view设置为不透明!
2 楼 啸笑天 2013-04-28  
2) 在适当的情况下使用reuseIdentifier

在适当的情况使用reuseIdentifier

在iOS程序开发中一个普遍性的错误就是没有正确的为UITableViewCells、UICollectionViewCells和UITableViewHeaderFooterViews设置reuseIdentifier。

为了获得最佳性能,当在tableView:cellForRowAtIndexPath:方法中返回cell时,table view的数据源一般会重用UITableViewCell对象。table view维护着UITableViewCell对象的一个队列或者列表,这些数据源已经被标记为重用了。

如果没有使用reuseIdentifier会发生什么?如果你在程序中没有使用reuseIdentifier,table view每次显示一个row时,都会配置一个全新的cell。这其实是一个非常消耗资源的操作,并且会影响程序中table view滚动的效率。

自iOS 6以来,你可能还希望header和footer views,以及UICollectionView的cell和supplementary views。

为了使用reuseIdentifiers,在table view请求一个新的cell时,在数据源中调用下面的方法:
1.static NSString *CellIdentifier = @"Cell";
2.UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

如果table view维护的UITableViewCell队列或列表中有可用的cell,则从队列从移除一个已经存在的cell,如果没有的话,就从之前注册的nib文件或类中创建一个新的cell。如果没有可以重用的cell,并且没有注册nib文件或类,tableview的dequeueReusableCellWithIdentifier:方法会返回一个nil。
1 楼 啸笑天 2013-04-28  
1) 使用ARC进行内存管理
ARC是在iOS 5中发布的,它解决了最常见的内存泄露问题——也是开发者最容易健忘的。ARC的全称是“Automatic Reference Counting”——自动引用计数,它会自动的在代码中做retain/release工作,开发者不用再手动处理。

下面是创建一个View通用的一些代码块:
1.UIView *view = [[UIView alloc] init];
2.// ...
3.[self.view addSubview:view];
4.[view release];

在上面代码结束的地方很容易会忘记调用release。不过当使用ARC时,ARC会在后台自动的帮你调用release。

ARC除了能避免内存泄露外,还有助于程序性能的提升:当程序中的对象不再需要的时候,ARC会自动销毁对象。所以,你应该在工程中使用ARC。

下面是学习ARC的一些资源:
苹果的官方文档

Matthijs Hollemans的初级ARC

Tony Dahbura的如何在Cocos2D 2.X工程中使用ARC

如果你仍然不确定ARC带来的好处,那么看一些这篇文章:8个关于ARC的神话——这能够让你相信你应该在工程中使用ARC!

值得注意的是,ARC并不能避免所有的内存泄露。使用ARC之后,工程中可能还会有内存泄露,不过引起这些内存泄露的主要原因是:block,retain循环,对CoreFoundation对象(通常是C结构)管理不善,以及真的是代码没写好。

这里有一篇文章是介绍哪些问题是ARC不能解决的 — 以及如何处理这些问题。

相关推荐

    iOS 7 Game Development (pdf书及源代码)

    You will gain a full understanding of the new Apple framework along with tips and tricks to interact with the game either by detecting taps, using sophisticated gesture recognizers, and moving ...

    Kindle Computer Science other.rar

    Database\Oracle Internals - Tips Tricks and Techniques for DBAs.mobi Database\OReilly High Performance MySQL.mobi Database\OReilly SQL and Relational Theory 2nd.mobi Database\OReilly SQL Cookbook.mobi...

    Apress Learn Cocos2D

    Explore advanced topics and unconventional approaches to game development, including tips and tricks for creating unique gameplay experiences and enhancing the marketability of games on the App Store....

    MATLAB实现参数化重采样时频变换(PRTF)用于振动与声音信号故障诊断

    内容概要:本文详细介绍了参数化重采样时频变换(PRTF)在振动与声音信号故障诊断中的应用。首先通过仿真信号展示PRTF的基本原理,即通过非线性时间轴映射提高时频分辨率,特别是在处理非平稳信号时的优势。接着讨论了PRTF的具体实现步骤,包括重采样、时频分析、坐标系转换等关键技术点。文中还提供了多个实际案例,如齿轮箱故障诊断、压缩机阀片断裂检测、蝙蝠回声定位信号处理等,展示了PRTF在不同应用场景中的灵活性和有效性。此外,文章分享了一些实用经验和技巧,如窗函数选择、抗混叠滤波、多尺度融合等,帮助读者更好地理解和应用PRTF。 适合人群:具备一定MATLAB编程基础和技术背景的信号处理工程师、研究人员。 使用场景及目标:适用于处理非平稳信号,尤其是振动和声音信号的故障诊断。目标是提高时频分辨率,清晰呈现故障特征,从而快速准确定位故障源。同时,也为研究者提供了一种新的信号处理工具,拓展了传统时频分析方法的应用范围。 其他说明:PRTF虽然强大,但在某些情况下并非最佳选择,如处理稳态信号或需要极高频率分辨率的任务。因此,使用者应根据具体情况选择合适的工具。此外,由于PRTF计算量较大,实时性要求较高的场景需考虑硬件加速或其他优化手段。

    毕设课设-基于MATLAB的汽车出入库识别系统.zip

    基于MATLAB的汽车出入库识别系统是一份适用于毕业设计或课程设计的项目,它主要围绕车辆进出仓库的自动识别技术开发。该系统充分利用MATLAB这一强大的数学计算和图形处理软件,实现了汽车识别的核心功能。 项目主要包括以下几个关键部分: 1. **图像采集与预处理**:通过摄像头或传感器捕捉汽车的实时图像,对图像进行预处理,如灰度化、边缘检测或特征提取,提高后续识别的精度。 2. **目标检测与识别**:利用MATLAB的机器视觉工具箱,可能采用了模板匹配、特征点匹配(如SIFT、SURF或HOG)、或者现代的深度学习技术(如卷积神经网络CNN),来识别出汽车的特征。 3. **车牌识别**:针对汽车的车牌进行识别,这通常涉及到字符分割、识别和验证,可能结合了OCR(Optical Character Recognition)技术。 4. **数据分析与管理系统**:收集并分析出入库数据,用于优化仓库管理策略,如实时流量监控、车辆调度等。 5. **文档与代码完整性**:项目不仅提供了完整的工作流程和算法实现,还包含了详尽的README.md文档,以便使用者了解项目的结构和使用方法,以及注意事项。 这个系统的优势在于将理论知识应用到实际场景中,既锻炼了学生的编程能力,也展示了MATLAB在计算机视觉领域的实用性。通过下载和交流,有助于参与者提升自己的技术能力,并推动自动化仓储系统的研发和优化。

    (源码)基于51单片机的密码锁控制器.zip

    # 基于51单片机的密码锁控制器 ## 项目简介 本项目是一个基于51单片机的密码锁控制器,通过结合LCD显示器和键盘,实现了一个简单的密码输入与验证系统。该系统可以用于需要密码保护的应用场景,如门禁系统、保险箱等。用户可以通过键盘输入密码,系统会根据输入的密码进行验证,并通过LED灯显示验证结果。 ## 项目的主要特性和功能 1. LCD显示功能使用LCD显示器实时显示密码输入的相关信息。 2. 密码设置与修改用户可以设置和修改一个4位数字(09)的密码。 3. 超级用户密码系统内置一个超级用户密码“1234”,用于特殊权限操作。 4. 密码验证反馈密码输入正确时,系统会亮绿灯密码输入错误时,系统会亮红灯。 ## 安装使用步骤 ### 前提条件 假设用户已经下载了本项目的源码文件,并具备基本的单片机开发环境(如Keil等)。 ### 步骤 1. 解压源码文件将下载的源码文件解压到本地目录。

    (源码)基于Python和强化学习算法的智能体训练系统.zip

    # 基于Python和强化学习算法的智能体训练系统 ## 项目简介 本项目是一个基于Python和强化学习算法的智能体训练系统,旨在通过深度学习和策略优化技术,训练智能体在复杂环境中进行决策和行动。项目结合了多种强化学习算法,如TRPO(Trust Region Policy Optimization),并使用了如Pommerman这样的复杂环境进行训练和评估。 ## 项目的主要特性和功能 强化学习算法包括TRPO在内的多种强化学习算法,适用于连续动作空间的强化学习任务。 环境模拟使用Pommerman环境进行智能体的训练和评估,环境包含复杂的棋盘布局和动态变化的炸弹、火焰等元素。 预训练与微调支持预训练模型的加载和微调,加速训练过程。 多模型评估支持多个模型的同时评估,比较不同模型在相同环境下的表现。 状态抽象与特征提取通过状态抽象和特征提取,优化智能体的决策过程。

    制造业2022年制造业上市公司高质量发展:城市群与主要城市百强企业分布分析

    内容概要:本文档展示了2022年中国制造业上市公司百强企业在不同城市群和城市的分布情况。从城市群角度看,百强企业主要集中在长三角(19家)、粤港澳(16家)和京津冀(11家)三大国家级城市群,这些地区凭借强大的发展基础、完善的产业链和优越的营商环境成为制造业高质量发展的领头羊。从具体城市分布来看,深圳和北京各有10家企业上榜,上海有9家。其中,深圳以比亚迪、中兴等大企业为代表,在营收规模上位居全国第一;北京依托科技和人才优势支持企业发展;上海则在高端制造业特别是集成电路领域处于领先地位。 适合人群:对中国经济地理、制造业发展趋势感兴趣的读者,以及从事相关行业研究的专业人士。 使用场景及目标:①了解中国制造业区域布局和发展趋势;②为政策制定者提供参考依据;③为企业投资决策提供数据支持。 阅读建议:建议重点关注各城市群和城市的具体数据,结合当地产业特色和发展优势进行分析,以便更好地理解中国制造业的空间分布规律及其背后的原因。

    房地产营销策划 -湖南涟源博盛生态园年度营销方案.pptx

    房地产营销策划 -湖南涟源博盛生态园年度营销方案.pptx

    基于粒子群算法PSO的宽带消色差超透镜Matlab设计与FDTD仿真

    内容概要:本文详细介绍了利用粒子群算法(PSO)在Matlab中设计宽带消色差超透镜的方法及其FDTD仿真验证。首先,通过定义合理的初始参数范围和适应度函数,将超透镜的纳米结构参数(如纳米柱的直径、高度、周期)作为粒子的位置,采用PSO进行优化。适应度函数结合了预存的相位延迟查找表和实时FDTD仿真结果,确保优化过程中能够高效评估不同结构参数的效果。文中还讨论了惯性权重的动态调整、震荡因子的引入以及适应度函数中物理约束的添加,以提高优化效果并防止陷入局部最优。最终,通过FDTD仿真验证优化结果,展示了在可见光波段内的聚焦效率和焦斑尺寸的改进。 适合人群:从事光学设计、超材料研究、电磁仿真领域的科研人员和技术开发者。 使用场景及目标:适用于需要设计高性能宽带消色差超透镜的研究项目,旨在通过粒子群算法优化超透镜结构参数,减少色差并提高聚焦效率。 其他说明:文中提供了详细的Matlab代码片段和FDTD仿真设置示例,帮助读者更好地理解和实施该方法。此外,强调了在实际应用中需要注意的参数选择和物理约束,以确保设计方案的可行性和有效性。

    FLAC 3D中深基坑支护结构(冠梁+钢支撑+钻孔灌注桩)的数值模拟及优化技巧

    内容概要:本文详细介绍了利用FLAC 3D软件进行深基坑支护结构的数值模拟方法,特别是针对冠梁、钢支撑和钻孔灌注桩的组合支护结构。文章首先解释了钻孔灌注桩的建模要点,强调了桩土接触面参数设置的重要性。接着讨论了钢支撑的激活时机及其对支护系统的影响,指出合理的开挖步控制可以更好地模拟实际情况。对于冠梁,则着重于其与桩顶的正确耦合方式以及弯矩分布的监测。此外,还分享了一些实用的经验教训和技术细节,如避免常见的建模错误、优化参数选择等。 适合人群:从事岩土工程、地下结构设计的专业人士,尤其是有一定FLAC 3D使用经验的研究人员和工程师。 使用场景及目标:适用于需要精确模拟深基坑开挖过程中支护结构行为的工程项目,旨在提高数值模拟的准确性,为实际施工提供科学依据和支持。 其他说明:文中提供了大量具体的FLAC 3D命令示例和实践经验,有助于读者快速掌握相关技能并在实践中灵活运用。同时提醒读者关注模型验证的重要性,确保模拟结果能够真实反映工程实际状况。

    前端铺子开发者 前端杂货铺 小程序在线课堂+工具组件小程序uniapp移动端.zip

    前端铺子开发者 前端杂货铺 小程序在线课堂+工具组件小程序uniapp移动端

    Delphi 12.3控件之geniso(CD iso Generator)可启动光盘文件制作器可执行文件.zip

    Delphi 12.3控件之geniso(CD iso Generator)可启动光盘文件制作器可执行文件.zip

    (源码)基于Arduino的传感器应用项目.zip

    # 基于Arduino的传感器应用项目 ## 项目简介 这是一个基于Arduino开发的项目集合,主要聚焦于传感器应用及相关开发。通过此项目,您将能够了解并实践如何使用Arduino进行硬件编程,以实现对各种传感器的读取和控制。 ## 项目的主要特性和功能 ### 1. 传感器读取 此项目包含多个示例,可以读取不同类型的传感器数据,如温度、湿度、光线、压力等。 ### 2. 实时数据反馈 通过Arduino,项目能够实现实时读取传感器的数据并在某些媒介(如LED灯、LCD显示屏等)上进行反馈。 ### 3. 自动化控制 根据项目需求,可以实现基于传感器数据的自动化控制,例如自动开关灯光、调节风扇速度等。 ## 安装使用步骤 ### 1. 下载源码文件 ### 2. 安装Arduino IDE 确保您的计算机上安装了Arduino IDE,这是编写和上传代码到Arduino设备所必需的。 ### 3. 导入项目文件

    房地产活动策划 -2025商业地产脆皮打工人春日养生局(万物回春主题)活动策划方案.pptx

    房地产活动策划 -2025商业地产脆皮打工人春日养生局(万物回春主题)活动策划方案.pptx

    h5py-3.1.0-cp37-cp37m-manylinux1_x86_64.whl

    该资源为h5py-3.1.0-cp37-cp37m-manylinux1_x86_64.whl,欢迎下载使用哦!

    基于Comsol仿真的远场涡流检测技术及其在工业探伤中的应用研究

    内容概要:本文详细介绍了利用Comsol软件进行远场涡流检测仿真的方法和技术要点。首先构建了一个二维轴对称模型,模拟了线圈和含缺陷铁磁管道之间的相互作用。文中强调了空气域大小、材料参数设置以及频率选择对检测效果的重要影响。通过调整不同的仿真参数如频率、线圈位置等,探讨了它们对磁场强度和相位变化的影响规律。此外,还分享了一些提高仿真效率的经验,例如合理的网格划分策略和参数化扫描的应用。最后指出远场涡流检测在工业探伤领域的潜在价值,特别是在检测埋地管道内部缺陷方面的优势。 适合人群:从事无损检测、电磁场仿真等相关工作的科研人员和技术工程师。 使用场景及目标:适用于希望深入了解远场涡流检测原理并掌握具体实施步骤的研究者;旨在为实际工程项目提供理论支持和技术指导。 其他说明:文中提供了大量实用的操作技巧和注意事项,有助于读者快速上手并在实践中优化自己的仿真流程。

    (源码)基于STM32F10x微控制器的综合驱动库.zip

    # 基于STM32F10x微控制器的综合驱动库 ## 项目简介 本项目是一个基于STM32F10x系列微控制器的综合驱动库,旨在为开发者提供一套全面、易于使用的API,用于快速搭建和配置硬件资源,实现高效、稳定的系统功能。项目包含了STM32F10x系列微控制器的基本驱动和常用外设(如GPIO、SPI、Timer、RTC、ADC、CAN、DMA等)的驱动程序。 ## 项目的主要特性和功能 1. 丰富的外设驱动支持支持GPIO、SPI、Timer、RTC、ADC、CAN、DMA等外设的初始化、配置、读写操作和中断处理。 2. 易于使用的API接口提供统一的API接口,简化外设操作和配置,使开发者能够专注于应用程序逻辑开发。 3. 全面的时钟管理功能支持系统时钟、AHB时钟、APB时钟的生成和配置,以及时钟源的选择和配置。 4. 电源管理功能支持低功耗模式、电源检测和备份寄存器访问,帮助实现节能和延长电池寿命。

    MACHIN3tools-1.0.1

    MACHIN3tools_1.0.1

    丰田功率分流混合动力系统Simulink建模及经济动力性仿真分析

    内容概要:本文详细介绍了丰田功率分流混合动力系统(如普锐斯)的Simulink分析模型及其经济性和动力性仿真的全过程。首先解析了该系统独特的双电机加发动机构型以及行星排耦合机制,接着阐述了Simulink模型的具体构建步骤,包括初始化参数设定、各模块的选择与配置。文中提供了多个代码示例,展示如何模拟不同工况下的动力输出和能耗情况,并强调了模型的高精度和实用性。此外,还探讨了模型的可扩展性和版本兼容性,以及一些关键的技术细节,如行星齿轮参数设定、能量管理模式、能耗计算方法等。 适合人群:从事混合动力技术研发的工程师和技术爱好者,尤其是对丰田THS系统感兴趣的读者。 使用场景及目标:①用于研究和开发新型混合动力系统;②为现有混合动力系统的改进提供参考;③作为教学工具,帮助学生理解和掌握混合动力系统的工作原理和仿真技术。 其他说明:该模型基于MATLAB 2021a版本构建,具有良好的版本兼容性和模块化设计,便于参数调整和功能扩展。同时,模型经过严格的验证,确保仿真结果与实际情况高度一致。

Global site tag (gtag.js) - Google Analytics