(GO) IOS best practices

Source: Internet
Author: User
Tags configuration settings http authentication naming convention git client notification center version control system install cocoapods

This article turns from http://www.jianshu.com/p/b0bf2368fb95

Thanks to the author and translator

iOS Best PracticesiOS Best PracticesTranslator note

This article is translated from Futurice's iOS good practices, and the translation is maintained on Github and published on a simple book.

This article issued a few days later found on the internet also has another translation version: http://ios.jobbole.com/81830/

The original title is iOS good practices, should be translated into iOS good practice/good practice, but it's a mouthful, and has been sent out, for the moment.

This article has not been the Daniel Review, flaws and the statement of the place, in Github, please make a lot of corrections.

The following is the text

Just like software, if we don't continue to improve this document, it will be outdated. We want everyone to help us improve it-just open a issue or send a pull request!

Interested in other platforms? Take a look at our Android development best practices and Windows App development best practices.

Why read this document

Jumping into the hole in IOS is really troublesome. Neither Swift nor Objective-c is widely used elsewhere, and the platform has its own naming of everything, and even debugging on a real machine is fraught with frustrations. Whether you're just getting started Cocoa or a developer who wants to correct your development habits, you can benefit from this document. But the following is just a suggestion, so if you have a better plan, try it!

Getting Started with Xcode

Xcode is a choice for most iOS developers and is the only official IDE supported by Apple. There are other options, such as Appcode, which are most famous, but unless you are an experienced developer, use Xcode. Do not care about its small shortcomings, it is now very good use.

To install Xcode, you only need to download Xcode in the Mac App Store. It will download the latest SDK and emulator at the same time, and you can download more content from Preferences > Downloads .

Project initialization

A common question when starting iOS development is to write all the view in code or use Interface Builder (storyboards or XIB). Both scenarios are considered. However, there are several considerations:

Why use code?
    • Storyboard it makes it difficult to merge code because its complex XML structure is prone to versioning conflicts.
    • It's easy to structure your code and reuse view to get your code DRY.
    • All the information comes together in one place. In Interface Builder you need to click on all the inspectors to find what you are looking for.
Why use Storyboard?
    • For less technical requirements, Storyboard uses a very good method of directly contributing to the project, for example, by adjusting the color or layout of the constraints. However, it requires a project to be configured, and the developer has some time to master the basics
    • Integration is faster when you can see changes without building a project
    • In Xcode6, custom text and UI elements can be visualized in the storyboard, much better than what you've changed in the code.
    • Starting with IOS8, Size Classes allows you to design screens for different types of devices without having to repeat some work
Ignore file

When putting the project into the version control system, there should be a good .gitignore file first. This way, unnecessary files (user settings, temporary files, and so on) will not be put into your repository. Fortunately, Github has given us the objective-c and Swift language templates

CocoaPods

If you plan to increase external dependencies (for example, third party libraries) in your project, CocoaPods provides a quick way to do it like this:

sudo gem install cocoapods

To get started, just run it in your IOS project directory:

pod init

It will create a podfile that will manage all your dependencies, add your dependencies in Podfile, and allow

pod install

To install third-party libraries and use them as part of workspace, your workspace will also contain your own projects. It is generally recommended to submit dependencies on your own projects, not each developer running after a checkout pod install .

Note that after that you need to open .xcworkspace instead .xcproject , otherwise your code will not be compiled, command:

pod update

All pods are upgraded to the latest version, and you can use a number of symbols to define your desired version requirements.

Project structure

To organize hundreds of source code files within a directory, it is best to set up some file structures based on your architecture. For example, you can use this:

├─ Models├─ Views├─ Controllers├─ Stores├─ Helpers

First, create them as Group (the Yellow directory) and navigate through your project with Xcode's project. Then for each project in the file, connect it to the real file directory-by opening it to the right of the file inspector, click on the Small directory icon, in your project directory to create a sub-directory with the name of the group.

Localization

In the beginning, all the strings displayed to the user should be placed in a localized file. This is not only convenient for translation, but also easy to find the text users see. You can specify a specific language by adding a startup parameter to the build Scheme

-AppleLanguages (Finnish)

For more complex translation problems, such as complex numbers (such as "1 person" and "3 people"), you should use .stringsdict format instead of an ordinary localizable.strings file. With this powerful tool to handle situations such as "one", "some", "few" and "many". When dealing with Russian and Arabic, you don't have to scratching.

For more information on localization, see the February 2012 helsink IOS Conference slides, most of which are now also applicable.

Constant

Create a file that was introduced by the prefix header Constants.h .

Do not use macro definitions (with #define ), defined with actual constants

static CGFloat const XYZBrandingFontSizeSmall = 12.0f;static NSString * const XYZAwesomenessDeliveredNotificationName = @"foo";

The constant type is safe and has a clearer scope (not available in all files that are not introduced). Cannot be redefined and can be used in the debugger.

Branching model

Especially when distributing your app (such as submitting to the app Store), it's best to differentiate the branch with a special tag. At the same time, the development of new features will introduce many commits and should be submitted on separate branches. git-flowis a tool to help you comply with this agreement. It simply wraps up the Git branch and tag commands to help maintain a proper branching structure. All development branches (for example develop ), about the tag branch of the app version, and the commit to the Master branch:

git flow release finish <version>
Common libraries

To put a third-party library into your project, it needs to be considered carefully. Indeed, a smart library might help you solve your current problems, but you might end up with a maintenance nightmare, such as after the next system version changes something, or a third-party library scenario becomes the official API. But in a well-designed code, switching implementations is easy. Try to think of Apple's broad (and excellent) framework.

This section tries to keep the cut short. Library features are designed to reduce template code (such as AutoLayout) or to solve complex problems that require a lot of testing, such as date calculations. When you're more professional in IOS, dig in the source code here and get to know them through their underlying Apple framework, and you'll find that you can do a lot of work.

Afnetworking

99.95% of iOS developers use this network library, and when NSURLSession themselves are perfect, they AFNetworking can still rely on position for the queue request management capabilities that many apps need.

Datetools Date Tool

Always, don't write your own date calculations. Fortunately, there is a Datetools MIT protocol, and after thorough testing, you can rest assured of using it when you need to use the date.

Auto Layout Library

If you prefer to write the interface in your code, you'll use Apple's hard-to-use ' nslayoutconstraint ' factory or Visual Format Language. The former is verbose, the latter is based on strings and is not conducive to compiler checking.

Masonry replaces constants with their own DSL, a similar library in Swift is cartography, which takes advantage of the language's rich operator overloading features. If more conservative, Flkautolayout provides a clean but not too much magic native API wrapper.

Architecture Architecture
    • Model-view-controller-store (MVCS)
      • This is Apple's default architecture (MVC), by extending a storage layer that represents the Model instance and processing the network, cache, and so on.
      • Each store RACSignal is returned by a void custom block method that either s or returns a value.
    • Model-view-viewmodel (MVVM)
      • Through "Massive view controllers": MVVM considers UIViewController subclasses to be part of the view and remains streamlined by maintaining state within the viewmodel.
      • is a very new concept for COCOA developers, but has been driven
    • View-interactor-presenter-entity-routing (VIPER)
      • The architecture that is worth looking at in a large project is complicated in MVVM and requires attention to testing.
Event mode

Here are some common ways to notify other objects:

    • Delegation (Delegate): _ (one-to-one) _ Apple often uses it (or too much). Use it to perform callbacks, for example, Model View makes a callback
    • Callback Blocks (callback code block): _ (one-to-one) _ can be more decoupled to maintain similar related code snippets. At the same time, there are a lot of sender than the delegate has a better extensibility.
    • Notification Center (Notification): _ (one-to-many) _ the most commonly used object to send an event to the first observer. Very decoupled-notifications can even be observed globally without reference to the distribution of objects
    • key-value Observing (KVO, key-value encoding): _ (one-to-many) does not require the observer to explicitly send the time, just as _key-value Coding (KVC) conforms to the observed key (attribute). It is not usually recommended because of his unnatural nature and cumbersome API.
    • Signals (signal): _ (one-to-many) _ Reactivecocoa's core, allowing links and combinations of your content, provides a way to prevent callback hell.
Models

Keep your model immutable and use them to change the semantics and types of remote APIs. Github's mantle is a good choice.

Views

When layout your view with Auto layout, make sure to include the following code in your parent class:

+ (BOOL)requiresConstraintBasedLayout{    return YES;}

Otherwise -updateConstraints , you may encounter strange bugs when the system is not called.

Controllers

It is recommended to use dependency injection, for example, to pass any required object as a parameter instead of maintaining all States in a single case. The latter method applies only when the state is truly global.

+ [[FooDetailsViewController alloc] initWithFoo:(Foo *)foo];
The traditional way of network: using callback block
// GigStore.htypedef void (^FetchGigsBlock)(NSArray *gigs, NSError *error);- (void)fetchGigsForArtist:(Artist *)artist completion:(FetchGigsBlock)completion// GigsViewController.m[[GigStore sharedStore] fetchGigsForArtist:artist completion:^(NSArray *gigs, NSError *error) {    if (!error) {        // Do something with gigs    }    else {        // :(    }];

This runs, but if you have multiple combinations of network requests, it goes into the callback nesting hell.

Reactive method: Using RAC signal

If you find yourself in a hell of a callback, look at Reactivecocoa (RAC), a versatile and versatile library that can change the way people write the entire app, but you can use it conservatively wherever it applies.

There are some excellent introductions to the concepts of RAC (and FRP in general) and functional programming on Teehan+lax and Nshipster.

// GigStore.h- (RACSignal *)gigsForArtist:(Artist *)artist;// GigsViewController.m[[GigStore sharedStore] gigsForArtist:artist]    subscribeNext:^(NSArray *gigs) {        // Do something with gigs    } error:^(NSError *error) {        // :(    }];

It allows the combination of signals and other signals to make some changes before they are shown.

Assets Resources

Asset catalogs is the best way to manage all your project visualization resources, and they can manage common and device-related iphone 4-inch, iphone Retina, IPAD, etc.) resources and automatically group them by their names. Telling your designers how to add them (Xcode has a built-in Git client) can save a lot of time, otherwise you'll have a lot of time to copy from the mail or other channels into the codebase. It allows the designer to immediately try to change the look of resources and experiment over and over again.

Using Bitmap Images with bitmaps

Asset catalogs only exposes the name of the image, the abstract name of the image set. This avoids conflicting resource names, just like [email protected] the file namespace within its picture set. Following some naming conventions can make life better:

IconCheckmarkHighlighted.png // Universal, non-Retina[email protected] // Universal, RetinaIconCheckmarkHighlighted~iphone.png // iPhone, non-Retina[email protected]~iphone.png // iPhone, Retina[email protected]~iphone.png // iPhone, Retina, 4-inchIconCheckmarkHighlighted~ipad.png // iPad, non-Retina[email protected]~ipad.png // iPad, Retina

Modifier suffixes -568h , @2x and ~iphone ~ipad is unnecessary, but there are them in the file, and when the files are dragged in, Xcode will dispose of them correctly. This avoids assignment errors.

Working with vector graphs

You can use the designer's original vector graphics (PDFs) to add to asset catalogs,xcode to automatically generate bitmaps from them. This reduces the complexity of your project (managing fewer files).

Code style naming

Although the naming convention is long, Apple has consistently adhered to the naming principle in the API.

Here are some basic principles that you should use:

A method begins with a verb to indicate that it does some side effects, but does not return anything:
- (void)loadView;
- (void)startAnimating;

Any method that begins with a noun has no side effects and returns the object it refers to:
- (UINavigationItem *)navigationItem;
+ (UILabel *)labelWithText:(NSString *)text;

Try to isolate both, for example, by not having side effects when manipulating data, and vice versa. This will let your side effects be included in the smaller granularity of the code, making debugging very difficult.

Structure

Pragma marks is a good way to group your code, especially in the view controller. The following structure can be applied to the work of most view controllers:

  #import "SomeModel.h" #import "SomeView.h" #import "SomeController.h" #import " SomeStore.h "#import" SomeHelper.h "#import <someexternallibrary/someexternallibraryheader.h>static NSString * Const Xyzfoostringconstant = @ "Foobarconstant"; static cgfloat const xyzfoofloatconstant = 1234.5; @interface Xyzfooviewcontroller () <XYZBarDelegate> @property (nonatomic, copy, readonly) Foo *foo; @end @implementation Xyzfooviewcontroller#pragma mark-lifecycle-(Instancetype) Initwithfoo: (Foo *) foo;-(void) dealloc; #pragma mark-view lifecycle-(void) viewdidload;-(void) Viewwillappear: (BOOL) animated; #pragma mark-layout-(void) makeviewconstraints; #pragma mark-public interface-(void) startfooing;-(void) stopfooing; #pragma mark-user interaction-(void) Foobarbutton Tapped; #pragma mark-xyzfoobardelegate-(void) Foobar: (Foobar *) foobar didsomethingwithfoo: (foo *) Foo; #pragma mark- Internal helpers-(NSString *) Displaynameforfoo: (foo *) Foo; @end  

The most important thing is to maintain consistency in your project's class

Other style guides

Our company does not have any company-level code-style guidelines, and it is useful to look at other developers ' objective-c style guides, even if the content is company-related or overly aggressive.

    • GitHub
    • Google
    • The New York times
    • Ray Wenderlich
    • Sam Soffes
    • Luke Redpath
Diagnostic compilation Warning

It is recommended that you turn on compilation warnings as much as possible and treat compilation warnings as if they were errors. Recommend this PPT. This slide covers how to eliminate the relevant warnings in a specific file, or in a special code snippet.

Simply put, at least the following values are defined in the _ "Other Warning Flags" compilation setting:

    • -Wall_ (Add a lot of warnings) _
    • -Wextra_ (add more warnings) _

Open "Treat warnings as errors" at the same time

Clang Static Analysis

The Clang compiler (Xcode uses) has a static parser to perform your code control and data flow analysis to detect many errors that the compiler cannot detect.

You can manually perform code analysis by manually running the product→analyze menu item inside Xcode

The parser can be allowed in shallow or deep mode, which is slower, but can analyze more problems from cross-function control flow and data flow

Recommended:

    • Turn on all parser checks (by opening all the "Static Analyzer" options in building setting)
    • Open "Analyze during ' Build" inside the release's compilation settings to allow the parser to automatically build the release version. (so you don't have to remember to run it manually)
    • Set "Mode of Analysis for ' Analyze '" to Shallow (faster)
    • Set the Mode of analysis for ' Build ' to
Faux Pas

Created by our own Ali Rantakari, Faux Pas is an excellent static error detection tool that analyzes your code and identifies problems you don't even find yourself. Use it before submitting your app to the App Store!

Debugging

When your App crashes, Xcode doesn't go into the debugger by default. In order to debug, you need to add an exception breakpoint (in Xcode's debug navigation midpoint "+") to exit execution when the exception occurs. In many cases, you need to look at the code that triggers these exceptions. It will catch any exception, even if it is already processed. If Xcode interrupts execution in a third-party library, for example, you may need to select Edit breakpoint and set Exception to objective-c.

For view debug, the two powerful visual inspection tools, Reveal and Spark Inspector, can save you a lot of time, especially if you're using Auto Layout and want to locate a problem or overflow view of the screen. Xcode offers a similar feature for free, but only works with IOS 8+ and is less useful.

Analysis

Xcode has an analysis tool called Instruments, which includes
Many of the tools that analyze memory, CPU, network traffic, graphics, and more, it's a bit complicated, but it's pretty straightforward when it comes to tracking memory leaks. Just select Product > Profile in Xcode, Select Allocations, click the Record button and use some useful strings to filter the information for the application space, such as the class name of your own app. It counts in a fixed column and tells you how many instances each object has. What exactly is the class that has been increasing the instance causes a memory leak.

Instruments also has automated tools for recording and running UI interactions as well as JavaScript files. UI Auto Monkey is a script that automates random clicks, swipes, and spins your app, which is useful in stress and penetration testing.

Statistics

It is highly recommended to use some statistical frameworks and they intuitively tell you how many people are using your app. Does the X feature increase the user? is the Y button hard to find? To answer these questions, you can send events, allow time and other recorded information to a service that aggregates them and visualize them. For example, Google Tag Manager. This is a much more useful place than Google Analytics where data can be inserted between apps and statistics, so the data logic can be modified through a Web service without updating your app.

A good practice is to create a simple helper class, for example XYZAnalyticsHelper , to process the internal model of the app and the data format (Xyzmodel, Nstimeinterval, ...) Transform to match the string-based data layer,

- (void)pushAddItemEventWithItem:(XYZItem *)item editMode:(XYZEditMode)editMode{    NSString *editModeString = [self nameForEditMode:editMode];    [self pushToDataLayer:@{        @"event": "addItem",        @"itemIdentifier": item.identifier,        @"editMode": editModeString    }];}

Another advantage is that you can replace the entire statistical framework when necessary without changing the rest of the app.

Crash Logs Crash Log

You should have your app send a crash log to a service. You can do it manually via Plcrashreporter and your own backend. However, it is highly recommended that you use existing services such as the following

    • Crashlytics
    • HockeyApp
    • Crittercism
    • Splunk mintexpress

When you're ready, make sure you save the Xcode archive ( .xcarchive ) for each app release. This archive contains binary and debug symbols for the built app dSYM , and you need to symbolize your Crash reports with each version-specific app.

Build Build Settings

Each simple app can be built in a different way, and the most basic separation is Xcode giving you a build-up between debug and release . The latter has more optimizations at compile time and may cause you to need to debug a few more problems. Apple recommends that you use the debug mode during development and use release settings when packaging. This is the default Scheme (The drop-down menu behind Play and Stop), and releaseis used when running run with debug settings and Archive.

Then, it seems too easy for the real app. You should not set up multiple development activities for testing, staging and other related. Each one may have its own URL, log level, bundle ID) so you can install them together as well as the description file. Then a simple debug/release difference cannot be separated from these, you can do more compilation settings in the Info tab of your project's settings.

About the build settings xcconfigFile

The build settings are usually defined by the Xcode GUI, but you can also use the configuration settings Files(" .xcconfig files") with the following advantages:

    • You can annotate
    • You can have #include other build settings files that can help you reduce duplication:
      • If you have some settings that apply to all build settings, add one Common.xcconfig and in the other build settings file#include
      • If you, for example, want to have a "Debug" Build settings file that allows compiler optimizations, you just need #include "MyApp_Debug.xcconfig" to reload the other settings
    • Conflict resolution and consolidation made easier

For more information on this topic, please see this PPT.

Targets

A target is at a lower level than the project. For example, a project might have multiple target, potentially overloading its project settings. To put it simply, each target is quite the same as an app. For example, you might have several apps (compiled from the same code) that were submitted to the app Store because of the country distinction. Each has a development/staging/release build, so it's best to differentiate by building settings rather than target. It is rare for an app to have only one target.

Schemes

Schemes tells Xcode what to do when you click Run, Test, Profile, Analyze, or Archive. They map these operations to a target and a build setting. You can pass the startup parameters, such as the language the app needs to allow (for testing localization) or some diagnostic flags for debugging purposes.

A suggested Scheme naming is MyApp (<Language>) [Environment] :

MyApp (English) [Development]MyApp (German) [Development]MyApp [Testing]MyApp [Staging]MyApp [App Store]

For most environments, the language component is unnecessary, and the app may be installed in a non-Xcode way, such as with TestFlight, and the boot parameters are ignored. In this case, the language of the device needs to be set manually in order to test localization.

Deployment

Deploying a software to an IOS device is not intuitive. But there are some core points of view that, if you understand, can be of great help to you.

Signature

When you need to run the software on a real device, you need to sign with an Apple-certified certificate . Each certificate is connected to a public and private key pair, and the private key is stored in the KeyChain of your Mac, and there are two types of certificates

    • Development Certificate: Each developer of the group has its own certificate, and it is requested by the special to. Xcode can do it for you, but it's best not to click on "Fix issue" to complete it, but to understand what it does. This certificate is required to deploy the development version to the device.
    • Publish a certificate: There can be multiple, but it's best to have one for each organization and share it through internal channels. This certificate is required when submitting your app to the App Store or your business's on-premises app store.
Description file

In addition to the certificate, there is a description file that connects the device to the certificate. Moreover, it is divided into two types of development and release.

    • Development ProvisioningProfile: A development profile that contains a list of all devices that can install the app. It connects one or more developers to allow this description file to use the certificate. A profile can confirm a particular app, but for most development purposes it is particularly well suited to use a wildcard profile, which is the Apple ID ending with an asterisk (*).
    • Distribution Provisioning Profile: Publish the description file itself, and there are different types for different use purposes. Each release profile is linked to a publishing certificate and is invalidated when the certificate expires.
      • Ad-hoc: Just like developing a certificate, it contains a whitelist of devices that an app can install. This profile can be used as a beta version and can test 100 devices per year. For more detailed testing and upgrading to 1000 test users, you can use Apple's recently released TestFlight service, Supertop provides a summary of its advantages and issues.
      • App Store: This profile does not list the device and anyone can install it via Apple's official release, which is required for all apps published in the App Store.
      • Enterprise : like the App Store, there is no device whitelist, and anyone through the intranet can be installed from the internal "app Store". The store may be just a connected web site. This description file is only allowed for enterprise account usage.

To sync all the certificates and profiles to your machine, you can go to Xcode's Preferences accounts, add your Apple ID, and then double-click your Team name. Then there's a refresh button at the bottom, and sometimes you need to restart Xcode to make things appear.

Debug Description file

Sometimes you need to debug a description file problem. For example, XCode may refuse to install the app to a device because the device is not in the list of profile devices that are being developed or Ad-doc published. In this case, you can use Craig Hockenberry's Provisioning plugin, browse ~/Library/MobileDevice/Provisioning Profiles , select a .mobileprovision file and use the SPACEBAR to invoke the Finder's Quick View feature, which will tell you about the device, entitlements, Information about the certificate and the Apple ID.

Upload

ITunes Connect is the back-end site where you manage apps uploaded to the App Store. Xcode 6 requires an Apple ID to sign and upload binary as a developer account. If you have multiple developer accounts and you want to upload their apps, you need a little bit of skill. Because an Apple ID can only be associated with one itunes connect account , one workaround is to create a new Apple ID for each itunes connect account, replacing X with application Loader Code to upload the app. This effectively relieves the .app coupling of uploading the final file build and signature.

After uploading the binary, it may take up to one hours to wait patiently. When your app appears, you can link to the corresponding app version and submit an audit

In-app purchases

When verifying an in-app purchase of receipt, remember to do the following steps:

    • authenticity: receipt is from Apple's
    • Integrity: receipt has not been tampered with
    • app match: Receipt's app bundle ID matches your app bundle ID
    • Product match: receipt with the same ID as you expect
    • freshness: You didn't verify the same receipt ID before

If possible, store your IAP storage-related content on the server side, and only in a legitimate receipt through the above checks. This design avoids the common theft mechanism, and because the server is verified, you can use Apple's HTTP Authentication service to replace your own PKCS #7 / ASN.1 format.

More information on this topic can be seen Futurice blog:validating In-app purchases in your IOS app

(GO) IOS best practices

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.