I created a simple HttpClient with AFNetworking.
HttpClient *client = [[HttpClient alloc] initWithTarget:(id)target
                                                 before:(SEL)before
                                                success:(SEL)success
                                                failure:(SEL)failure
                                                timeout:(SEL)timeout]
So the controller can register callback function when it perfroms the HTTP request. And here is how I wrote the callback functions:
- (void)successMethod:(id)response {
  //  LogDebug(@"Success: %@", response);
  self.lock = false;
  if (self.target == nil || self.successCallback == nil) {
    return;
  }
  if ([self.target respondsToSelector:self.successCallback]) {
    [self.target performSelector:self.successCallback withObject:response];
  }
}
But here I found a problem. When the request comes back fast, it works fine. But if the request comes back after a very longtime and meanwhile, user changes the view. Then it crashes the app and throw an exception like, selector can not be performed on a nil object.
So what I want know whether I did it in the right way and is there any way to solve this problem? What is the best practices to implement this?
=====
Update:
Sorry I didn't put the error log. But actually there is no much information I can get. Sometime there is even no log. I put a screenshot here and hope it can help.
I only get this and there is no exception log.

==== Update
And hope this can help
#import "HttpClient.h"
#import "AFNetworking.h"
#import "Logging.h"
@interface HttpClient ()
@property int retryCounter;
@property(nonatomic) NSString *action;
@property(nonatomic) NSString *url;
@property(nonatomic) NSDictionary *param;
@property(nonatomic) AFHTTPRequestOperationManager *manager;
@end
@implementation HttpClient
- (id)initWithTarget:(id)target
              before:(SEL)before
             success:(SEL)success
             failure:(SEL)failure
             timeout:(SEL)timeout {
  self = [super init];
  if (self) {
    self.target = target;
    self.before = before;
    self.success = success;
    self.failure = failure;
    self.timeout = timeout;
    self.lock = false;
    self.retryMaxCounter = 2;
    self.retryCounter = 0;
    self.manager = [AFHTTPRequestOperationManager manager];
    self.manager.requestSerializer = [AFJSONRequestSerializer serializer];
    self.manager.responseSerializer = [AFJSONResponseSerializer serializer];
  }
  return self;
}
- (void)request:(NSString *)action
            url:(NSString *)url
          param:(NSDictionary *)param {
  self.action = action;
  self.url = url;
  self.param = param;
  [self beforeMethod];
  [self request];
}
- (void)request {
  if (self.lock) {
    return;
  }
  if ([[self.action lowercaseString] isEqual:@"get"]) {
    // Get
    LogDebug(@"Send GET request.");
    self.lock = true;
    LogInfo(@"%@\n%@", self.url, self.param);
    [self.manager GET:self.url
        parameters:self.param
        success:^(AFHTTPRequestOperation *operation, id responseObject) {
          [self successMethod:responseObject];
        }
        failure:^(AFHTTPRequestOperation operation, NSError error) {
          if ([operation.response statusCode] == 500) {
            [self failureMethod:operation.responseObject];
          } else {
            [self timeoutMethod];
          }
        }];
  } else if ([[self.action lowercaseString] isEqual:@"post"]) {
    // POST
    LogDebug(@"Send POST request.");
    self.lock = true;
    LogInfo(@"%@\n%@", self.url, self.param);
    [self.manager POST:self.url
        parameters:self.param
        success:^(AFHTTPRequestOperation *operation, id responseObject) {
          [self successMethod:responseObject];
        }
        failure:^(AFHTTPRequestOperation operation, NSError error) {
          if ([operation.response statusCode] == 500) {
            [self failureMethod:operation.responseObject];
          } else {
            [self timeoutMethod];
          }
        }];
  } else {
    LogError(@"Not supported request method.");
  }
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
- (void)beforeMethod {
  LogDebug(@"Before requesting.");
  if (self.target == nil || self.before == nil) {
    return;
  }
  if ([self.target respondsToSelector:self.before]) {
    [self.target performSelector:self.before];
  }
}
- (void)successMethod:(id)success {
  //  LogDebug(@"Success: %@", success);
  self.lock = false;
  if (self.target == nil || self.success == nil) {
    return;
  }
  if ([self.target respondsToSelector:self.success]) {
    [self.target performSelector:self.success withObject:success];
  }
}
- (void)failureMethod:(id)failure {
  LogDebug(@"Failure: %@", failure);
  self.lock = false;
  if (self.target == nil || self.failure == nil) {
    return;
  }
  if ([self.target respondsToSelector:self.failure]) {
    [self.target performSelector:self.failure withObject:failure];
  }
}
- (void)timeoutMethod {
  LogError(@"Request timeout.");
  self.lock = false;
  self.retryCounter++;
  if (self.retryCounter < self.retryMaxCounter) {
    [self request];
  } else {
    if (self.target == nil || self.timeout == nil) {
      return;
    }
    if ([self.target respondsToSelector:self.timeout]) {
      [self.target performSelector:self.timeout];
    }
  }
}
#pragma clang diagnostic pop
@end
Thank you all very much!
==== Update
I found the problem. It was because I set the targe to assign instead of weak. For the difference between assign and weak, please refer to stackoverflow question