IOS app from Click to start

Source: Internet
Author: User
Tags posix uikit

Start from exec () before program starts

The main () function is the entry for the entire program, and the EXEC () function is called before the program starts. The difference between exec and system in UNIX is that the system uses the shell to invoke the program, which is the equivalent of the Fork+exec+waitpid,fork function that normally calls the EXEC function to execute a new program after creating the child process. , and exec is directly letting your program run instead of the original program.

The system executes the commands in a separate process and returns to your program. and the EXEC function is to execute the new program directly in your process, the new program will overwrite your program, unless the call goes wrong, you can no longer return to the code after exec, that is, the current program becomes the exec call of the program.

UNIX provides 6 different exec functions for our use.

#Include<unistd.h>IntExecl(ConstChar *pathname,ConstChar *arg0, .../* (char *) 0 */);IntExecv(ConstChar *pathname,char *Const argv[]);IntExecle(ConstChar *pathname,ConstChar *arg0, .../* (char *) 0, char *const envp[] */);IntExecve (const char *pathname, char *const argv[], char *const envp[]); int EXECLP  (const char *filename, const char *arg0, ... /* (char *) 0 */); int EXECVP  (cosnt char *filename, char *const argv[]);             

Through analysis, we find that the parameter table of the EXEC function with L and V is passed differently. An EXEC function with the end of E passes a list of environment variables. The EXEC function with the end of P takes the file name of the new program as a parameter, while the other exec function takes the path of the new program.

Returns 1 if there is an error in the function and no return value if successful. Only EXECVE is the real system call, and the others are packaged library functions on this basis.

The function of the EXEC function family is to find the executable file according to the specified file name and use it to replace the contents of the calling process, in other words, execute an executable file inside the calling process. The executable file here can be either a binary file or a script file that can be executed under any UNIX.

IOS System Architecture

Mac system is a UNIX kernel-based graphical operating system, Mac OS and iOS system architecture comparison analysis found that Mac OS and iOS system architecture level is only the top layer, MAC is the Cocoa framework, and iOS is the Cocoa Touch framework, The rest of the architecture hierarchy is the same.


Core OS is an open source OS called Darwin, rewritten with FreeBSD and Mach, and is a UNIX core that is open, POSIX compliant. This layer includes and provides basic functionality for the entire iphone OS, such as: Hardware drivers, memory management, program management, thread Management (POSIX), File system, network (BSD sockets), and standard input and output, all of which are provided through the C language API.


The driver of the core OS layer provides the interface between the hardware and the system framework. However, due to security considerations, only limited system framework classes can access the kernel and drivers. The iphone OS offers many interface sets to access the low-level features of the operating system, and iphone apps access these features through the Libsystem library, which set thread (POSIX threads), network (BSD sockets), File system access, standard I/O, Bonjour and DNS services, on-site information (locale information), memory allocations, and math calculations.

Core Services provides richer functionality on core OS, including Foundation.framework and core Foundation.framework, which is called Foundation, It is because it provides a series of basic functions to deal with strings, permutations, combinations, calendars, times, and so on.

The foundation is the Api,core fundation belonging to Objective-c, which belongs to the C API. In addition, core Servieces provides features such as security (for handling authentication, password management, security management, etc.), core location, SQLite, and Address Book.

The Core Infrastructure Framework (Corefoundation.framework) is a C-based interface set that provides basic data management and service capabilities for iphone applications. The framework supports collection data types (Arrays, sets, etc.), Bundles, string management, date and time management, raw block management, preference management, URL and stream operations, threading and running loops (run Loops), Port and socket communication.

The core infrastructure is closely related to the underlying framework, which provides the Objective-c interface for the same basic functionality. If developers mix the foundation Objects and Core Foundation types, they can take advantage of the "toll-free bridging" technology (bridging) that exists in two frameworks. Toll-Free bridging enables developers to use the core foundation and the underlying type of either of these two frameworks.

Static link library and dynamic link library

There are several related files in iOS: Dylib, dynamic link library (also known as DSO or DLL), Bundle, cannot be linked Dylib, can only be loaded at runtime using Dlopen (), can be used as MacOS plugin. The Framework, a folder that contains Dylib and resource files and header files.

A dynamic-link library is a set of source code modules, each containing a number of functions that can be called by an application or other dynamic-link library, and when an application invokes a function inside a dynamic-link library, the operating system maps the file image of the dynamic-link library to the address space of the process. This allows all threads in the process to invoke functions in the dynamic-link library. Dynamic Link Insecure library after the download is complete, this time the dynamic link library for the thread in the process is only some of the code and data placed in the address process space, the operating system in order to save memory space, the same dynamic link library in memory only one, the operating system will only be loaded once into memory.

Because the code snippet's in-memory permissions are read-only, when multiple applications load the same dynamic-link library, you don't have to worry about the application modifying the code snippet of the dynamic-link library. When a thread calls a function of a dynamic-link library, the function takes the arguments passed to him in the inline stack and uses the line Cheng to store the variables he needs, and any object created by the dynamic-link library function is either the calling thread or the calling process owned, and the dynamic-link library does not have any objects. If a function in the dynamic-link library calls VirtualAlloc, the system will reserve the address from the address space of the calling process, even if the mapping of the dynamic-link library is revoked, and the scheduled address of the calling process will persist until the user cancels the booking or the process ends.

Both static and dynamic link libraries are shared code, and if you use a static link library, the instructions in Lib are all directly included in the resulting package file, whether you want to or not. However, if you use the dynamic link library, the dynamic link library does not have to be included in the final package, and the package file can "dynamically" reference and unload the dynamic link library file that is separate from the installation package when it executes. Another difference between a static-link library and a dynamic-link library is that the static-link library can no longer contain other dynamic-link libraries or static libraries, and other dynamic or static link libraries may be included in the dynamic-link library.

The name of the static function library in Linux is generally libxxx.a, and the files compiled from the static function library are larger because all the data of the library is integrated into the target code. The compiled execution program does not require external library support because all the functions used are already compiled. This, of course, will also be a disadvantage, because if the static library changes, then your program must be recompiled.

The name of the dynamic function library is generally libxxx.so, relative to the static function library, the dynamic function library is not compiled into the target code when it is compiled, and your program executes to the relevant function to call the corresponding function in the library, so the dynamic function library produces the smaller executable file. Since the library is not integrated into your program, it is applied and invoked dynamically while the program is running, so you must provide the appropriate library in the running environment of the program. The change of dynamic function library does not affect your program, so the upgrade of dynamic function library is more convenient.

The static and dynamic libraries in iOS development are relatively compile-time and run-time. A static library is linked to the target code when it is compiled, and it is no longer necessary to load a static library when the program is run. Dynamic libraries are not linked to the target code when they are compiled, but are loaded only when the program is running, because the existence of a dynamic library is also required during the program's run.

The static library in iOS can be represented by a. A or. framework file, in the form of a. Dylib and. Framework. The. Framework of a system is a dynamic library, usually built by itself. The framework is a static library.

. A is a pure binary file. There are resource files in the framework in addition to binaries.. a files cannot be used directly, at least with. h file mates: Framework files can be used directly,. A +. H + sourcefile =. Framework.

One of the important features of dynamic libraries is Plug and play, and we can choose to load dynamic libraries when we need them. If you do not want to load the dynamic library as soon as the software starts, you need to

Targets-->Build Phases-->Link Binary With Libraries

The corresponding status in *.framework is changed from the default Required to Optional, or the xx.framework is removed from the Link Binary with Libraries list.

You can use Dlopen to load the dynamic library, and the real executable code in the dynamic library is the xx.framework/xx file.

- (ibaction) Usedlopenload: (ID) sender{nsstring *documentspath = [nsstring StringWithFormat:@ "%@/documents/xx.framework/xx", nshomedirectory ()]; [self Dlopenloadlib:documentspath];} -(void) Dlopenloadlib: (nsstring *) Path{libhandle = null;libhandle = Dlopen ([path Cstringusingencoding: Nsutf8stringencoding], Rtld_now); if (libhandle = null) {char * Error = Dlerror (); nslog (@ "Dlopen Error:%s", error);} else {nslog (@ "Dlopen load Framework success. ")}}               

You can also use NSBundle to load a dynamic library, implementing the following code:

- (ibaction) Usebundleload: (ID) sender{nsstring *documentspath = [nsstring StringWithFormat:@ "%@/documents/xx.framework", nshomedirectory ()]; [self Bundleloadlib:documentspath];} -(void) Bundleloadlib: (nsstring *) Path{_libpath = path;< Span class= "hljs-built_in" >nserror *err = nil; NSBundle *bundle = [nsbundle bundlewithpath:path]; if ([bundle Loadandreturnerror:&err]) {nslog (@ "bundle Load framework success. ");} else {nslog (@ "bundle load Framework err:%@ ", err);}}              

You can add a listener callback for loading and removing a dynamic library, and there is a complete sample code on GitHub where you can see that an engineering software starts up with more than 120 dynamic libraries loaded, even if it's a blank project.

However, it is important to note that not calling Dlopen () in the initialization method has an impact on performance. Because Dyld runs before the App starts, because it is single-threaded, the system cancels the lock, but Dlopen () turns on multi-threading and the system has to lock, which seriously affects performance and can cause deadlocks and unknown consequences. Therefore, do not create threads in the initializer.

It is said that iOS can now use a custom dynamic library, and the lower version needs to be manually loaded with Dlopen (). The dynamic library shelves will have some auditing rules, such as not using x86/i386 packages and ARM architecture packages Lipo. Such as:

lipo –create Release-iphoneos/libiphone.a Debig-iphonesimulator/libiphone.a –output libiphone.a

This will combine the static library files of the simulator and the device into one file output.

Shanghai has a company has a successful listing of cases, but I did not test in this regard, as to whether can be examined, but also need to verify.

Dylib Load Call

Based on the above analysis, at exec (), the system kernel maps the application to the new address space, and each start location is random. Then using DYLD to load the Dylib file (dynamic-link library), Dyld's work in the app process is to load all the dynamic-link libraries that the app relies on, ready to run everything it needs, with the same permissions as the app.

When loading dylib, get a list of dependent dynamic libraries that need to be loaded from the header of the main execution file, find each dylib, and then open the file to read the file start location to make sure it is a mach-o file (for different runtime executable file types). Then find the code signature and register it with the kernel.

The Dylib file that the application relies on may be dependent on other dylib, so the dynamic library list is a recursive dependency collection. General applications load 100 to 400 dylib files, but most are system dylib, which are pre-computed and cached and loaded quickly. However, loading embedded (embedded) dylib files takes time, so try to merge multiple inline dylib into one to load, or use static archive.

After loading all the dynamic-link libraries, they are only in a separate state, and the code signature makes it impossible to modify the instructions so that one dylib can call another dylib. By fix-up They can be combined, and what Dyld is doing is correcting (fix-up) pointers and data. There are two types of fix-up, rebasing (the pointer is adjusted inside the mirror) and the binding (pointing the pointer to content outside the mirror).

Because there is a dependency between the dylib, many operations in the dynamic library are recursively operated along the dependency chain, and the rebasing and the Binding correspond to both recursiverebase () and Recursivebind () respectively. Because it is recursive, the Dorebase () and Dobind () methods are called from the bottom up, so that the dependent dylib is always preceded by the dylib that relies on it to perform rebasing and Binding.

Rebaing consumes a lot of time on I/O, before rebasing and binding determine whether pre-binding. If pre-binding (prebinding) is already in place, then the fix-up process of rebasing and binding is not required because the pre-bound address is already loaded.

The binding handles pointers to external dylib, which are actually bound by the symbol name and are a string. Dyld needs to find the symbol corresponding to the implementation, in the symbol table to find a lot of calculations, found after the content will be stored. The binding appears to be computationally larger than rebasing, but requires very little I/O operations because the rebasing has already been done for the binding. Many of the data structures in objective-c are fixed by rebasing and Binding (fix-up), such as pointers to the superclass in class and pointers to methods.

OC Call

C + + generates initializers for statically created objects, unlike static languages, where OC can instantiate an object of a class with the name of the class, based on the runtime mechanism. Runtime maintains a global table of mapped class names and classes, and when a dylib is loaded, all of its defined classes need to be registered with the global table. OBJC can change the offset of an instance variable by fix-up in a dynamic class at load time, using this technique to add another Dylib class method without changing the dylib, rather than the usual way to change a class by defining a category.

The dependencies of the master execution file and the associated dylib form a huge graph of the graphs, the execution initializer loads the leaf nodes first, and then progressively loads the intermediate nodes up until the root node is loaded at last. This loading order ensures security, and the rest of the dylib files that it relies on must have been preloaded before loading a dylib. The final DYLD will call the main () function. Main () calls Uiapplicationmain () and the program starts.

Program Startup logic

Using Xcode to open a project, it is easy to find a file--main.m file, here is the entrance to the application. When the program starts, the main function is executed first, the main function is the entry point of the iOS program, the Uiapplicationmain function is called internally, and a UIApplication object is created in the Uiapplicationmain. Then create the UIApplication delegate Object--(your) appdelegate, turn on a message loop (main Runloop) and notify Appdelegate whenever a corresponding system event is heard.

int main(int argc, char * argv[]) {@autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));}}

The UIApplication object is a symbol of the application, and each application has its own UIApplication object, and it is a singleton. This singleton object can be obtained by [UIApplication Sharedapplication], and the first object created after the launch of an iOS program is the UIApplication object, using the UIApplication object, Can perform some application-level operations.

The Uiapplicationmain function is implemented as follows:

int UIApplicationMain{  int argc,  char *argv[],  NSString *principalClassName, NSString * delegateClassName}

The first parameter represents the number of arguments, the second parameter represents the array of loaded functions, the third argument is the UIApplication class name or its subclass name, and if nil, the UIApplication class name is used by default. The fourth parameter is the instantiated object name of the protocol Uiapplicationdelegate, which is the corresponding method that notifies the UIApplication object when it hears the change of the system.

When it starts, it calls the Didfinishlaunching method, creates the UIWindow in this method, sets the Window property of the Appdelegate, and sets the UIWindow root controller. If there is a storyboard, the application's entry storyboard is found in Info.plist and the controller that the arrow refers to is loaded, displaying the window. The biggest difference between storyboard and Xib is that storyboard is based on an attempted controller rather than a view or window. The display will add Rootviewcontroller view to UIWindow above (this step will create the controller's view)

[window addSubview: window.rootViewControler.view];

Each application has at least one UIWindow, which manages and coordinates the screen display of the application, and Rootviewcontroller's view will be the first view of the UIWindow.


Booting without using the storyboard

The complete process for starting the program is as follows:

1.main function

2.UIApplicationMain

    • Create a UIApplication object

    • Create a UIApplication delegate object

    • Delegate object starts processing (listening) system events (no storyboard)

    • When the program is started, the agent's application:didfinishlaunchingwithoptions is called: method

    • Create UIWindow in Application:didfinishlaunchingwithoptions:

    • Create and set Rootviewcontroller for UIWindow

    • Display window

3. According to Info.plist to obtain the most important storyboard file name, load the main storyboard (with storyboard)

    • Create UIWindow

    • Create and set Rootviewcontroller for UIWindow

    • Display window

Proxy methods for Appdelegate

When the app is finished, it will be called-(BOOL) Application: (UIApplication *) Application didfinishlaunchingwithoptions: (Nsdictionary *) launchoptions{}The app loses focus and is called-(void) Applicationwillresignactive: (UIApplication *) application{}//app into the background when the call, generally save the app's data (game data, such as pause game)-(void) Applicationdidenterbackground: (uiapplication *) application{} //app program from the background back to the foreground will be called-(void) Applicationwillenterforeground: (uiapplication *) application{} //app program gets focus will be called-(void) applicationdidbecomeactive: (uiapplication *) application{}//memory warning, you may want to terminate the program and clear memory that you do not need to use again-(void) applicationdidreceivememorywarning: (UIApplication *) Application{}//program is about to exit call-(void) Applicationwillterminate: ( uiapplication *) application{}        

Appdelegate load Order
1.application:didfinishlaunchingwithoptions:
2.applicationDidBecomeActive:

Loading order in the Viewcontroller
1.loadView
2.viewDidLoad
3.viewWillAppear
4.viewWillLayoutSubviews
5.viewDidLayoutSubviews
6.viewDidAppear

Load order in view
1.initWithCoder (call initWithFrame if not storyboard, here are two methods as one)
2.awakeFromNib
3.layoutSubviews
4.drawRect

The time to use some methods

(void)load;

The application starts the method that is called, and the code written in this method is called first.

(void)initialize;

Used in this class is called, this method is generally set the theme of the navigation controller, etc., if the following method to set the navigation bar theme is too late!

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions;

This method will create UIWindow, set up the root controller and display, such as some applications to load the authorization page is also in this addition, you can set the observer, listen to the notification switch root controller and so on.

(void)awakeFromNib;

The use of this method is only involved when using IB, When the. nib file is loaded, a awakefromnib message is sent to each object in the. nib file, and each object can define its own awakefromnib function to respond to the message and perform some necessary actions. In this method, set the background of the view and a series of common operations.

(void)loadView;

Create a hierarchy of views that cannot be written directly without creating a view of the controller Self.view because the bottom of Self.view is:

if(_view == nil){_view = [self loadView]}

Writing this will directly cause a dead loop.

If you rewrite this loadview method, it will show a black screen if nothing is written.

(void)viewWillLayoutSubviews;

The view is going to layout the child view, Apple suggested the method of setting the interface layout property, this method and Viewwillappear, the system bottom is not write any code, that is, it is possible to not write super.

(void)layoutSubviews;

In this method, the frame of the child control is generally set.

- (void)drawRect:(CGRect)rect;

The UI controls are all painted, and in this step you draw everything up. The DrawRect method can only be called once at load time, and if you need to call it later, such as the arc of the download progress, you need to always brush the frame, use Setneedsdisplay to call this method several times.

- (void)applicationDidBecomeActive:(UIApplication *)application;

This is the Appdelegate application to get the focus method, really here, is all things loaded complete.

Start analysis

When the app starts, it plays a startup animation. On the iphone is the 500ms on the 400ms,ipad. If the app starts too slowly, the user will give up and never even come back again. To prevent an application from taking up too much system resources, the Apple engineer who developed iOS designed a "watchdog" mechanism. In different scenarios, the watchdog monitors the performance of the application. If the runtime is exceeded, the watchdog forces the process of terminating the application.

When the IOS app starts, it links and loads the framework and static LIB, performs Uikit initialization, and then enters application callbacks, executes core Animation transaction, and so on. Each framework increases startup time and memory usage, does not link unnecessary frameworks, and the necessary framework does not mark as optional. Avoid creating global C + + objects.

The font, status bar, user defaults, Main.storyboard are initialized when Uikit is initialized. User defaults is essentially a plist file, the saved data is deserialized at the same time, do not save big data such as pictures in user defaults.

For OC, you should minimize the number of Class,selector and category metadata. Theories like coding principles and design patterns encourage people to write more sophisticated and short classes and methods, and separate each part of the method into one category, but this increases the startup time. Use the initializer where it is called, and do not use \\atribute((constructor)) to explicitly mark the method as an initializer, but rather let the initialization method call. For example, use Dispatch_once (), pthread_once (), or std::once (). That is, it is initialized during the first use and delays some of the work time.

Before establishing the network connection needs to do the domain name resolution, if the gateway problems, DNS resolution is not normal, the DNS time-out is not the application control. These problems should be considered when programming, if the program starts with a network connection, should end the boot process as soon as possible, network access through the thread to resolve, without blocking the main thread of the run.



Wen/Wu Bai (Jane book author)
Original link: http://www.jianshu.com/p/231b1cebf477
Copyright belongs to the author, please contact the author to obtain authorization, and Mark "book author".

IOS app from Click to start

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.