Afnetworking source code analysis and interview test site extension


Recently, I reread the source code of afnetworking 3. X. it’s a review of the old to learn the new. Also combed some excellent code details and interview test points, listed down, found that this library is small and exquisite, it is a treasure house for beginners.

What do you think of open source library?

First of all, reading high-quality open source code library is definitely an effective way for programmers to improve themselves quickly. How to read the source code efficiently is also a problem. I don’t know if anyone has read it before, but I don’t feel that I have gained much.

Here are some of my code reading experiences:

  1. Think more, ask more questions, for example

    • What is the overall code structure? What is the relationship between classes? Why design like this?
    • Does the code involve multithreading? What is the thread model? What kind of problems can be applied to this multithreading scheme?
    • What design patterns are used in the code? How is it realized?
  2. You can also pay attention to the details of the code, do not let go when you encounter unfamiliar usage, more research can lay a solid foundation

    aboutAFNetworkingSome excellent code details, I also sort out a part here, you can refer to the following

  3. Be sure to take notes and summarize, to share better.

    Referring to Feynman learning method, I think this is the best way to deepen understanding and strengthen memory. With the increase of age, memory will decline, there is a note to review, can save a lot of time to remember again. In addition, sharing more with others can also enhance their influence, communicate with others to verify, and also be able to find and fill their own gaps.

The code structure of afnetworking 3. X

Or backAFNetworkingHere, the code structure of AF should be understood by most people. Here I will briefly introduce it.AFNetworking 3.xThe code structure of 2. X is much simpler than that of 2. X, which is mainly due to Apple’s optimization of network related API

  • AFURLSessionManager/AFHTTPSessionManager

    This is the core of AF code, which is mainly responsible for the initiation of network requests and callback processing. It is a layer of encapsulation on the system network related API. Most of the logic is inAFURLSessionManagerIt’s inside,AFHTTPSessionManagerIt is designed to provide some convenient methods for HTTP requests. If you need to extend the functions of other protocols (such as FTP protocol), you can consider usingAFURLSessionManagerCreate a subclass.

  • AFURLRequestSerialization/AFURLResponseSerialization

    These two brothers mainly deal with some work related to parameter serialization.AFURLRequestSerializationIs to construct the passed in parameter asNSURLRequest, such as custom header, some post or get parameters, etc.AFURLResponseSerializationIt mainly returns the data from the systemNSURLResponseWe need to process the response object, such as JSON, XML, image and so on

  • AFSecurityPolicy

    Handle public key and verification logic related to HTTPS. At present, due to the opening of Apple ATS, basic HTTPS has become a standard configuration. Although CA is usually used to verify the server’s public key directly, we don’t need to do any additional configuration. However, starting from here, by the way, I’d like to explore the knowledge points related to HTTPS. I feel it’s quite common. Please refer to the following for the specific interview questions

  • AFNetworkReachabilityManager

    This is actually a relatively independent module, providing the function of obtaining the current network state.

  • UIKit+AFNetworking

    Here, we mainly provide a convenient method of UIKit through category

Some good code details of AF

After a careful look at the code, we found that the common OC basic knowledge has specific applications in AF, and most of them are interview questions. Here is also a record and carding.

  • Method of creating singleton
+ (instancetype)defaultInstance {
    static AFImageDownloader *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    return sharedInstance;

Must know must know_ Once to ensure that only one instance is created when multithreading calls.

  • dispatch_ Sync and dispatch_ barrier_ Solve the problem of parallel read and serial write with sync
//Note the parallel queue
self.requestHeaderModificationQueue = dispatch_queue_create("requestHeaderModificationQueue", DISPATCH_QUEUE_CONCURRENT);

//Serial write, pay attention to the specific execution time of barrier block
dispatch_barrier_sync(self.requestHeaderModificationQueue, ^{
    [self.mutableHTTPRequestHeaders setValue:value forKey:field];

//Parallel read, pay attention to the execution order when the above write operation is executed at the same time
NSDictionary __block *value;
dispatch_sync(self.requestHeaderModificationQueue, ^{
    value = [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders];

GCD uses barrier to deal with parallel read and serial write

  • The usage of weakself and strongself
__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusCallback callback = ^(AFNetworkReachabilityStatus status) {
    __strong __typeof(weakSelf)strongSelf = weakSelf;

    strongSelf.networkReachabilityStatus = status;
    if (strongSelf.networkReachabilityStatusBlock) {

    return strongSelf;

Weakself avoids circular references, and strongself ensures that self will not be released during the internal execution of block

  • Other uses

    Nssecurecoding, KVO, Swizzle, nsstream, nsprogress, code comment, pragma mark, etc

Possible interview sites for afnetworking

As mentioned earlier, when reading the open source library, we should think more and ask more questions. Here are some interview questions

How can afnetworking 2. X start resident child threads? Why do I need to resident a child thread?

This knowledge point should be what interviewers like to ask in af2. X version. There is a detail in af2. X version. A resident sub thread is opened through runloop. The specific code is as follows:

+ (void)networkRequestThreadEntryPoint:(id)__unused object {
    @autoreleasepool {
        [[NSThread currentThread] setName:@"AFNetworking"];

        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        [runLoop run];

+ (NSThread *)networkRequestThread {
    static NSThread *_networkRequestThread = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
        [_networkRequestThread start];

    return _networkRequestThread;

First of all, we need to understand why we need to open itpermanentChild thread?

NSURLConnectionThe interface of is asynchronous, and then it will call back in the initiated thread. And a child thread, after the synchronization code is executed, generally, the thread exits. So you want to receiveNSURLConnectionThe child thread must survive at least until the time of callback. The reason why AF allows a thread to reside is that when multiple HTTP requests are initiated, callback processing will be carried out uniformly in this sub thread, so it is simply allowed to survive.

As mentioned above, a child thread will exit after executing a task. Under what circumstances can a child thread continue to survive? This involves the second problem, how AF starts resident threads. In fact, what we are looking at here is the basic knowledge of runloop.

About runloop, it is recommended to read “in depth understanding of runloop”. I think it is very detailed. In short, runloop will not exit when it finds that there is still source / timer / observer. So AF adds an nsmachport to the current runloop. This port is actually relative to adding a source event source. In this way, the runloop of the child thread will be in a loop state, waiting for other threads to send messages to this port. In fact, AF does not send messages to this port.

In addition to this processing method of AF, Apple also provides a callback thread solution

// NSURLConnection
- (void)setDelegateQueue:(nullable NSOperationQueue*) queue

// NSURLSession
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;

Apple provides an interface that allows you to make an operation queue for callback execution. Therefore, when af3. X is used, a queue with concurrency of 1 is directly created to handle callbacks.

Expansion issues:

Now that runloop is mentioned, consider the extension of runloop

  • Does the child thread have runloop by default? When is the time to create and destroy runloop?
  • What are the modes of runloop? When sliding, I find that the timer has no callback. Why?
  • In addition to the above method of addport to keep threads alive, is there any other method?

Is it necessary to create a new mananger for the relationship between afurlsession manager and nsurlsession?

If we look at the code carefully, we should be able to come to the conclusion that the relationship between manager and session is 1-to-1, and AF will create the corresponding nsurlsession when the manager is initialized. Similarly, AF also states in the comments that it can provide a configured manager singleton for global reuse.

So reusing a manager is actually reusing a session, and what are the benefits of reusing a session?

In fact, session started to support http2.0 after IOS 9. One of the characteristics of http2.0 is multiplexing (refer to “multiplexing in HTTP series (2) http2”). Therefore, multiplexing session here is to use the multiplexing characteristics of http2.0 to reduce the time and resources of re establishing TCP connection when accessing the same server.

Official documents also recommend using different sessions in different functional scenarios. For example, one session deals with ordinary requests, one session deals with background requests, one session deals with open requests, one session deals with privacy requests, and so on.

How can afsecuritypolicy avoid man in the middle attacks?

Now, as Apple’s ATS strategy is basically switched to HTTPS, the basic principle of HTTPS still needs to be understood. We don’t want to introduce it here. If you need, please refer to the relevant articles in Google.

Usually, first of all, we need to understand man in the middle attack. Generally speaking, the hacker intercepts the certificate returned by the server and forges his own certificate. Usually, the tools we use such as Charles / Fiddler can actually be regarded as man in the middle attack.

The solution is very simpleSSL PinningAFSecurityPolicyOfAFSSLPinningModeThis is the related settings.

SSL PinningThe principle of TLS is to package the server’s public key into the client. When TLS is used to verify, the server’s certificate will be compared with the local certificate. If it is consistent, the verification will be allowed.

typedef NS_ENUM(NSUInteger, AFSSLPinningMode) {
    Afsslpinningmodepublickey, // only verify the public key in the certificate
    Afsslpinningmodecertificate, // verify all fields of the certificate, including the period of validity

Due to the existence of validity period of digital certificate, there will be the problem of validation failure after it is built into the client, so it can be set toAFSSLPinningModePublicKeyIn this way, as long as the public key in the certificate remains unchanged after the certificate is renewed, it can pass the verification.


YesSSL PinningIs it safe?

Reference article:

Why do I no longer need resident threads after afnetworking 3.0?

Don’t say you know afnetworking 3.0/nsurlsession

Afsecuritypolicy of afnetworking source code

How to set up secure connection of afnetworking correctly

Link to the original text:…

Welcome to WeChat official account.
Afnetworking source code analysis and interview test site extension

Recommended Today

Summary of recent use of gin

Recently, a new project is developed by using gin. Some problems are encountered in the process. To sum up, as a note, I hope it can help you. Cross domain problems Middleware: func Cors() gin.HandlerFunc { return func(c *gin.Context) { //Here you can use * or the domain name you specify c.Header(“Access-Control-Allow-Origin”, “*”) //Allow header […]