The fourth harvest and thinking of reading AFNetworking source code

Because the main method of get request in this version is here:

    AFHTTPOperation *operation = [AFHTTPOperation operationWithRequest:request callback:callback];

Next, we will add breakpoints to analyze the class of AFHTTPOperation:

AFHTTPOperation inherits from qhttpoperation, qhttpoperation inherits from QRunLoopOperation, and QRunLoopOperation finally inherits from NSOperation.

Add breakpoints to see the execution order:

1.
+ (id)operationWithRequest:(NSURLRequest *)urlRequest callback:(AFHTTPOperationCallback *)callback {
    return [[[self alloc] initWithRequest:urlRequest callback:callback] autorelease];
}

2.

- (id)initWithRequest:(NSURLRequest *)urlRequest callback:(AFHTTPOperationCallback *)callback {
    self = [super initWithRequest:urlRequest];
    if (!self) {
        return nil;
    }
    //Acceptable content types
    self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/plain", nil];
    self.callback = callback;
    
    return self;
}

3.
#pragma mark - QRunLoopOperation

- (void)operationDidStart {
    [super operationDidStart];
    [[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidStartNotification object:self];
}

4.
- (void)finishWithError:(NSError *)error {
    [super finishWithError:error];
    
    NSDictionary *data = nil;
    if (self.contentTypeAcceptable) {
        if ([[self.lastResponse MIMEType] isEqualToString:@"application/json"]) {
            NSError *jsonError = nil;
            //            data = [[JSONDecoder decoder] parseJSONData:self.responseBody error:&jsonError];
            data = [NSJSONSerialization JSONObjectWithData:self.responseBody options:kNilOptions error:&jsonError];
            
        }
    }
    
    if (self.statusCodeAcceptable) {
        [[NSNotificationCenter defaultCenter] postNotificationName:AFHTTPOperationDidSucceedNotification object:self];
        
        if(self.callback.successBlock) {
            data = [NSJSONSerialization JSONObjectWithData:self.responseBody options:kNilOptions error:nil];
            
            self.callback.successBlock(self.lastRequest, self.lastResponse, data);
        }
    } else ......
	
	//At this time, the data can be printed and the callback method has gone:
	//Requested data dic:{
    code = 0;
    data =     {
        area = "";
        "area_id" = "";
        city = "\U5317\U4eac";
        "city_id" = 110100;
        country = "\U4e2d\U56fd";
        "country_id" = CN;
        county = XX;
        "county_id" = xx;
        ip = "182.48.105.88";
        isp = "\U8054\U901a";
        "isp_id" = 100026;
        region = "\U5317\U4eac";
        "region_id" = 110000;
    };
}

5.
- (void)dealloc {
    [_callback release];
    [super dealloc];
}
	

This is the order in which this class is executed,

However, the parent class is involved. See Step 3:

#pragma mark * Start and finish overrides

- (void)operationDidStart
    // Called by QRunLoopOperation when the operation starts.  This kicks of an 
    // asynchronous NSURLConnection.
{
    assert(self.isActualRunLoopThread);
    assert(self.state == kQRunLoopOperationStateExecuting);
    
    assert(self.defaultResponseSize > 0);
    assert(self.maximumResponseSize > 0);
    assert(self.defaultResponseSize <= self.maximumResponseSize);
    
    assert(self.request != nil);
    
    // If a debug error is set, apply that error rather than running the connection.
    
    #if ! defined(NDEBUG)
        if (self.debugError != nil) {
            [self finishWithError:self.debugError];
            return;
        }
    #endif

    // Create a connection that's scheduled in the required run loop modes.
        
    assert(self.connection == nil);
    self.connection = [[[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO] autorelease];
    assert(self.connection != nil);
    
    for (NSString * mode in self.actualRunLoopModes) {
        [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:mode];
    }
    
    [self.connection start];
}

@property (retain, readwrite) NSURLConnection * connection;

NSURLConnection appears ~! ~

Popularization of knowledge: (1) assert is a macro in C. Used for assertion.

The function of assert is to evaluate the expression. If its value is false (that is, 0), it first prints an error message to stderr, and then stops the program by calling abort.

NSAssert can only be used in Objective-c. It is an extension of assert. It can catch the exception of assert class and print some readable logs

(2) NSString *scheme = [URL scheme]; / / take out the protocol header

Two important pieces of code:

 assert(self.connection == nil);
    self.connection = [[[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO] autorelease];
    assert(self.connection != nil);
    
    for (NSString * mode in self.actualRunLoopModes) {
        [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:mode];
    }
    
    [self.connection start];
	

Next, I'll use the old NSURLConnection to make a get request. Include an analysis of why runloop is used here?

Keywords: Mobile JSON

Added by rich1983 on Mon, 04 Nov 2019 16:26:56 +0200