I. Alamofire core Modules Overview
Let's take a holistic look at the Alamofire framework relationship and outline some of the core modules. Let's take a look at the file organization structure of Alamofire, and then give the relationships of the classes in these file organization structures. Therefore, in this part of the classification chart is indispensable. Nonsense less to go into that part of the subject.
1.Alamofire Directory Structure parsing
First we look at the Alamofire directory structure, from the overall to control the Alamofire. Below is the Alamofire framework of all the files, the file is not too much, alamofire framework of the source code is not too much, all clear alamofire frame structure is not difficult. Below is all the files in the Alamofire, the core folder is Alamofire, features is mainly the core file extension. Today we take the core document as the main, feature file as a supplement to spy on the Alamofire framework of the source code.
Below is a brief description of the features of each file under the core folder:
-
Alamofire.swift----This file is primarily to provide users with some convenient methods of invocation, the user can directly invoke the convenient method in the file to use the Alamofire-related features.
-
Manager.swift----Manager defines the session object, session-related delegate, and delegate-executed queue and other related information to create a request object in the manager to initiate requests. Manager manages all kinds of requests, and manager objects are open to the outside in a single case.
-
Request.swift----The file as its name, is responsible for creating the session of the various tasks, and execute the relevant sessiontask, and call the relevant book parsing function module to parse the data and return to the user through a callback.
-
The Parameterencoding.swift----is responsible for the various encodings of the request parameters (URLs, Urlencodedinurl, JSON, propertylist, etc.), and returns the encoded data with the result of the urlrequest combination.
-
Result.swift----encapsulates the parsed data into a result object.
-
The Response.swift----is responsible for encapsulating the server's corresponding data to generate the Response object, which includes the result object described above, and the user will eventually get to the Response object in the form of a closure callback.
-
Notifications.swift----which is a notification struct that defines a number of strings that are key to the required notification when the network requests Didresume, Didsuspend, Didcancel, Didcomplete will give notice.
-
Error.swift----which is an error structure, which encapsulates a variety of fault states.
Summary of the functions of each file under the Features folder:
-
Download.swift-----extends the manager and request classes so that they support down Task, which encapsulates the nsurlsessiondownloaddelegate related proxy methods.
-
Upload.swift----is also an extension of the manager and request classes in this file, enabling it to support Upload Task, which encapsulates the proxy method that obtains the progress of uploading data in nsurlsessiondatadelegate. That is, the Taskdidsendbodydata proxy method.
-
Multipartformdata.swift----The file can be seen from the name in order to organize data uploaded by multiple forms of data, upload task in the use of multipartformdata.
-
Stream.swift----are similar to download and upload files, which also extend the manager and rquest to support the transmission of data streams, The main encapsulation and implementation of Nsurlsessionstreamdelegate related agent method.
-
Responseserialization.swift----This file is primarily an extension of data parsing for the request class. It encapsulates a variety of parsing methods for response data, including data, String, JSON, PropertyList, and so on.
-
Networkreachabilitymanager.swift---- This file is mainly for the systemconfiguration.framework in the scnetworkreachability related things encapsulated, mainly for the management and monitoring of network state changes.
-
Servertrustpolicy.swift----This file is mainly for the extension of Nsurlsession, which defines a variety of network request authentication strategy, the main certificate certification related things.
-
Timeline.swift----The file is for debugging purposes, which records the timing of the relevant operation and records it for ease of use at debug time.
-
Validation.swift----is primarily used to verify the success of a request, and to do so if something goes wrong.
The above is an overview of all the files in Alamofire, which is a general understanding of the Alamofire framework. Combined with the above overview, to study the Alamofire source code is still relatively clear. Below is the wood structure of the relevant files in Alamofire 3.4, as follows:
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160615162837370-931573636. PNG "width=" 269 "height=" 479 "style=" margin:0px;padding:0px;border:none; "/>
2. Structure between the core classes
It simply describes the directory structure of the Alamofire framework and the content that each file is responsible for. Next we go to the inside of each file to see the relationship between the core classes as a whole. Below is the "class diagram" of the core class, of course, just below the core class. The following is an overview of the class diagram below, because it is too large to look very clear here, if you are interested, you can save as, and then zoom in to view.
-
The section in the black box below corresponds to the content in Alamofire.swift. This is mainly the extension of some URL conversion strings and the extension of Urlrequst to Mutableurlrequest, as well as some convenient ways for users to use them.
-
The yellow box is the content of our Manager.swift, the manager class object is presented in the form of a singleton, the convenient method in the black box above, mainly obtains the manager class's singleton, then calls the corresponding method.
-
The green box corresponds primarily to the contents of the Request.swift and features folders, mainly the request class and its extension, and of course the extensions to the manager and Nsurlsession.
-
The red box is the encapsulation of the callback methods for the various tasks of the network request session, which provide a default implementation in these callback methods, and leave a callback block on the outside to allow the user to implement the callback methods themselves.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160615155319026-200429460. PNG "width=" 941 "height=" 581 "style=" margin:0px;padding:0px;border:none; "/>
Second, Alamofire.swift source code Analysis
The first part is an overview of the various components of the Alamofire framework, and then it's time to go into each of these modules to see how they are implemented and organized. Or "clues", first from the user to see the place to start, and then layer deep, until you can not see the place. So the second part, let's take a look at the content in Alamofire.swift, because the file is the entrance to the Alamofire framework.
The class diagram structure in 1.alamofire.swft
The class diagram below is the larger version of the black box in the first category, according to the Alamofire.swift this file we are not difficult to draw below this class diagram. One thing to say is that in the class diagram omitted some traversal methods, only write some of the main, but the core function is still there. Below the urlstringconvertible and urlrequestconvertible are responsible for the type conversion interface, please see below for details. This file, in addition to the method of type conversion, is a convenient way to invoke the manager's singleton.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160616150136526-139203436. PNG "width=" 763 "height=" 442 "style=" margin:0px;padding:0px;border:none; "/>
2.alamofire.swift Technical Details
Below is the implementation of the Urlstringconvertible protocol and related extensions, the main function is to convert the URLs in string, Nsurl, Nsurlcomponents, nsurlrequest into string types. The type to be converted follows the Urlstringconvertible protocol and returns the converted string in the calculated variable urlstring. As shown below, this type conversion method is often used in development, and other instances are given below. The functionality of the Urlrequestconvertible protocol is similar to urlstringconvertible, The Urlrequestconvertible protocol is responsible for converting nsurlrequest into Nsmutableurlrequest type. Do not do too much to repeat here.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160616150852495-513322786. PNG "width=" 397 "height=" 383 "style=" margin:0px;padding:0px;border:none; "/>
Below is a convenient method in Alamofire.swift, other convenient methods similar to this, are called the corresponding method in the manager singleton, convenient method in order to chain call the request class related methods, so all the convenient method will return the current manager singleton use Request object 。 The following are the specific examples:
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160616151603432-618020096. PNG "width=" 421 "height=" 263 "style=" margin:0px;padding:0px;border:none; "/>
3. Extending Use Cases
Apply your knowledge and extrapolate. The above kind of "protocol-oriented" Development of the idea is worth learning, before in the design pattern related to the series of blog more than once mentioned to "interface Programming", where the protocol is the interface. Although the above only uses protocols for simple type conversion, this idea is very worthwhile for us to learn. With the above type conversion, we can write down the code below. The code below is not the code in the Alamofire framework, which I implemented based on an instance of the type conversion above, defines a type conversion protocol, the type to be converted to follow this protocol, and the following string for example, as shown below.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160616152527526-1395571074. PNG "width=" 425 "height=" 361 "style=" margin:0px;padding:0px;border:none; "/>
Third, Manager.swift source code Analysis
Because the convenience method is primarily a singleton of the calling manager class, let's look at what's in Manager.swift. The manager class is primarily responsible for the initialization of the session and request, and provides the default implementation of the Sessiondelegate proxy method. In implementing the Proxy method, the corresponding closure has been provided to the user to use the closure of the corresponding proxy method. The Sessiondelegate class in Manager is the proxy class for nsurlsessiondelegate and related sub-protocols, which gives the default implementation of each proxy method, and defines a series of closure callback variables at implementation time. When these closure variables are not empty, the contents of the closure block are executed, and the provided default implementations are not executed.
1.manager.swift Related class diagram
The lower class diagram is a larger version of the yellow part, mainly the relationship between the manager class and the sessiondelegate. It is not difficult to see from the class diagram below that the Sessiondelegate class follows the Nsurlsessiondelegate protocol and the Sub-Protocol, and gives the corresponding implementation method of the agent. The code below gives the specific encapsulation and implementation of the agent.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160616171825042-971856481. PNG "width=" 783 "height=" 580 "style=" margin:0px;padding:0px;border:none;line-height:1.5; "/>
Related properties of the 2.Manager class
Come to the point, because the manager class is used externally in a single case, so let's take a look at the single implementation of the manager class. The Sharedinstance computed property below is the manager's Singleton, where a manager object is stored. When we created the Manager object, we specified a defaultsessionconfiguration and a defaulthttpheaders for the Nsurlsession object stored in the manager object.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160616174315151-1665599636. PNG "width=" 683 "height=" 131 "style=" margin:0px;padding:0px;border:none; "/>
The above is the implementation of the single example in the manager class, and then we will parse the core properties in the class, and below are some of the core attributes:
-
Defaulthttpheaders property: Defaulthttpheaders is a computed property in the manager class that organizes the contents of the default request header.
-
Session property: The type of the property is of type nsurlsession, which is responsible for requesting the session and creating various session tasks.
-
Queue property: This property is a serial queue that is responsible for performing the task of creating session task session.
-
Delegate property: This property is of type Sessiondelegate, and Sessiondelegate class follows Nsurlsessiondelegate and its sub-protocols, and gives the corresponding implementation. The sessiondelegate is highlighted below. The delegate property here is responsible for invoking the corresponding callback method in the Sessiondelegate class.
Request method for 3.Manager class
The implementation of the request method is given in the Manager.swift source file, and the upload, download and other methods called by the manager class are extended in other source files. The methods of extension are discussed later in this section, and the request method is parsed first. The method below is the one that we invoke using the manager class's singleton in the convenience method. The method parameter indicates the request method (GET, POST, put, etc.), the urlstring parameter is the request address, and parameter is the request parameter. The encoding parameter is the encoding of the request parameter, where URL encoding is the default. Headers dictionary parameter is the request header information, the default is nil. The code below basically creates the Nsmutableurlrequest object, then encodes the parameters into the Nsmutableurlrequest object, and then calls the request () method to initiate the requests.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160617100251823-1917606287. PNG "width=" 794 "height=" 288 "style=" Margin:0px;padding:0px;border:none; "/>
The code snippet below is the request () method called in the above function, and the request () method below is responsible for creating the Datatask through the session, which is responsible for executing the data Task task. The data task object that is created is then passed to the request object when the object of the request class is initialized. The Task delegate object of the request object is then stored in the delegate attribute of the manager class. Because the proxy method in the delegate property is called by the method of the corresponding task delegate, it is necessary to store it here. Then call the Resume () method of the request object to initiate the network request for the data. To call other methods of the request object in a chained way, the object of the request class is returned. The code looks like this:
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160617101239104-772146672. PNG "width=" 713 "height=" 367 "style=" margin:0px;padding:0px;border:none; "/>
4. Sessiondelegate parsing in Manager
Sessiondelegate can be said to be a proxy agent because there is a subdelegates dictionary property in Sessiondelegate that is responsible for storing the individual task Delegate in the request object. Instead, Sessiondelegate calls the method in the task delegate through the stored task delegate in the corresponding proxy method, so Sessiondelegate says it is the proxy agent.
The code snippet below is part of the code in the Sessiondelegate class, where the Subdelegates dictionary attribute stores the taskdelegate in the request. Subdelegatequeue is a parallel queue used to synchronously perform get and set task delegate objects in the dictionary. It then defines a subscript for the Sessiondelegate class, which is the function of adding and getting the corresponding task Delegate in the form of a session task as subscript to subdelegates. The custom subscript lets the object of the class use the subscript form to set and get the value of the property, and later gives the extended demo.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160617104514604-1938318373. PNG "width=" 757 "height=" 513 "style=" margin:0px;padding:0px;border:none; "/>
For the proxy method implemented in Sessiondelegate, let's take an example of the Didreceivedata proxy method that executes the data task request. Below is the Didreceivedata proxy method in Sessiondelegate. The code is relatively simple, first of all to determine whether the Proxy method object closure callback variable has a value, if there is to execute the closure callback block, if there is no value to obtain our stored data task Delegate, and then go to execute the data task The Didrecivedata method in delegate. Other methods are similar to this, so on the point of the surface, here do not do too much to repeat.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160617105806307-1485174922. PNG "width=" 798 "height=" 135 "style=" margin:0px;padding:0px;border:none; "/>
5. Knowledge Point Expansion
Then there is the time to extrapolate, to expand the knowledge point. Next we'll create a small example to see how the custom subscript in Swift is going to be. Boulevard to Jane, next we will simplify the use of the above subscript, create a demo, and then use this demo to introduce the subscript.
The code snippet below is an example of the simplified version we created, which supports custom subscripts in Swift's class, and self-labeling allows you to access and set properties in the following form. The following is a custom subscript that sets and returns the value of a Value property in the subscript. The usage is as follows:
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160617111447057-239073882. PNG "width=" 668 "height=" 340 "style=" margin:0px;padding:0px;border:none; "/>
Four, Request.swift source code Analysis
Gradually, we now come to the Request.swift class, because the request in the manager above finally goes to the location of the request class, so the next thing we want to analyze is the contents of the Request.swift source file. The Request.swift source file is primarily a data task request that executes and implements the method in the corresponding data task delegate. Other tasks such as download task, Upload task,stream task, etc. will perform these tasks when the request is extended in other files. Let's take data task as an example here. The request class is plainly responsible for creating the corresponding task through the session and implementing the Proxy method for the corresponding task.
1. Request related class diagram
The following class diagram is the request-related class diagram, where the request class and its extension are created with various types of tasks and then given the corresponding task Delegate. The following class diagram gives an inheritance relationship between various task delegate. The request related source file also encapsulates the callback method in the closure state when given the implementation of the Taskdelegate proxy method. This approach is consistent with the practice in sessiondelegate. A detailed description is given below.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160617135343088-1496555994. PNG "width=" 865 "height=" 598 "style=" margin:0px;padding:0px;border:none; "/>
Initialization method for 2.Request classes
Below is the initialization method of the request class, which requires two parameters, the first parameter is an object of nsurlsession, which is the object of the session created in the manager's Singleton. While the second parameter is the manager, but the task of initializing tasks has to be given to the request class, and the manager is simply defining a nsurlsessiontask type to send to the request. For example, in the manager's request () method, the task in the upload () method of Nsurlsessiondatatask,manager is the Nsurlsessionuploadtask type.
In the initialization method of the request, the type of task provided by the manager Singleton is determined to create datataskdelegate, uploadtaskdelegate, and so on. The corresponding task is created in the corresponding task delegate. We also take the above datatask as an example, if you invoke the request () method in the manager singleton, the initialization of the datataskdelegate () below is performed. As shown below:
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160617135931323-1486841479. PNG "width=" 746 "height=" 296 "style=" margin:0px;padding:0px;border:none; "/>
The above delegate are of the taskdelegate type, because Uploadtaskdelegate, downloadtaskdelegate, and datataskdelegate are all taskdelegate subclasses, So the object-oriented "polymorphism" is used here. The following two properties are the delegate and task properties in the request class, delegate initialization is in the initialization method of the requset above, and the task here is a storage property, and the task initialization is in the corresponding taskdelegate. After you create the Task object in Taskdelegate, assign it to the task property in the request class as follows:
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160617141215370-282717548. PNG "width=" 625 "height=" 109 "style=" margin:0px;padding:0px;border:none; "/>
3. Progress closures in the Requset class
When using the request class object, we can chain-invoke the method in request, the most common is to get the progress of the corresponding task execution, which is usually I use the progress () method. The code snippet below is the implementation of the Progress () method. By the type of the task Delegate to determine which task is currently performed, and then assign the progress closure to the corresponding task Delegate, in these task Delegate in the corresponding callback method to get the task execution progress, Then execute the incoming closure below.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160619162619304-183142590. PNG "width=" 661 "height=" 176 "style=" Margin:0px;padding:0px;border:none; "/>
4.Request Resume () method
Below is the resume () method in the request class, where the code is relatively simple. It is primarily used to record starttime and then call the resume method of the task to begin the task. Of course, after the start of the task to initiate the appropriate notification, here is a didresume notification. All of the notification types are stored in the notifications structure in the Notifications.swift file. Other methods in the request class, such as the Suspend (), Cancel () method, are implemented in a similar way to resume (), and will be notified accordingly, without too much repeating.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160619163438773-1170776934. PNG "width=" 689 "height=" 118 "style=" Margin:0px;padding:0px;border:none; "/>
Related proxy classes in the 5.Request class
From the class diagram in the first section we can see the proxy class associated with the request class, and Taskdelegate is the base class for all proxy classes. In this proxy class, you define the necessary properties and the corresponding callback methods in the Nsurlsessiontaskdelegate, and provide the corresponding closure callback for these callback methods. Here, take the Taskdelegate proxy class as an example. Below is the closure method provided by the Taskdelegate proxy class for the corresponding proxy method in Nsurlsessiontaskdelegate. Other proxy classes such as Datataskdelegate, Downloadtaskdelegate, and so on are similar. The corresponding proxy method is the callback is processed, but before processing will determine whether the corresponding closure is nil, if not nil, then execute the contents of the closure closure block. If nil, the default processing provided is performed.
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/545446/201606/545446-20160619165014179-709691434. PNG "width=" 720 "height=" "style=" margin:0px;padding:0px;border:none; "/>
In detail, this Alamofire core class has been introduced, because space is limited, other classes here do not do too much to repeat. Other classes, as well as other files, are outlined in the first section, and their implementation details are not too much, and the code shared on GitHub gives comments on the key technical details of these classes.
Extensions, closures, and enumeration associated values are used extensively in the Alamofire framework. Especially when parsing the data of the network request, the closure type as the parameter of the function, and then through the closure variable to provide the corresponding resolution scheme, in this do not do too much to repeat, other technical details "benevolent see". Listen to me more, see more technical Blog if not personally to understand, say more is useless, practice out of the truth.
iOS development Alamofire Source Depth analysis