AFNetworking

Through the previous learning of the basic knowledge of HTTP protocol, the difference between GET/POST request, the use of NSURLConnection and NSURLSession, I have basically understood the method of network request, but it is relatively troublesome to use. AFNetworking is the encapsulation of NSURLConnection and NSURLSession, which makes network requests easier and easier. It is a very useful third-party framework. AFNetworking3.0 removes support for NSURLConnection. Take a look at AFNetworking’s history and framework




AFNetworking version updated




AFNetworking framework

All of these are available on GitHub, you can check them out on GitHub.

Use of AFNetworking

1. GET request

AFHTTPSessionManager *manager =[AFHTTPSessionManager manager]; NSDictionary *dict = @{ @"username":@"520it", @"pwd":@"520it" }; / / the parameters parameter dictionary [manager GET: @ "http://120.25.226.186:32812/login" parameters: dict progress: ^ (NSProgress * _Nonnull DownloadProgress) {// progress // progress} success:^(NSURLSessionDataTask * _Nonnull task, ResponseObject = responseObject; // responseObject = responseObject; // task = responseObject; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {// error error message}];Copy the code

2. A POST request

AFHTTPSessionManager *manager =[AFHTTPSessionManager manager]; NSDictionary *dict = @{ @"username":@"520it", @"pwd":@"520it" }; [manager POST: @ "http://120.25.226.186:32812/login" parameters: dict progress: ^ (NSProgress * _Nonnull downloadProgress) { } success:^(NSURLSessionDataTask * _Nonnull task, * (NSURLSessionDataTask * _Nullable responseObject) {NSURLSessionDataTask * _Nullable responseObject) NSError * _Nonnull error) {// Request failed}];Copy the code

Note: We found that the GET request is exactly the same as the POST request, just with a different name. The GET request can also put parameters in the dictionary, or it can concatenate parameters after the URL and pass parameters nil. In addition, there is no need to enable Task because the AFN has already enabled Task for us. In addition, the AFN treats the data returned to us by the server as JSNO data by default, and the AFN has already converted the response body JSON data into OC objects, usually dictionaries or arrays. What about the XML returned by the server? In this case, we need to set the AFN parsing method ourselves

manager.responseSerializer = [AFXMLParserResponseSerializer serializer];Copy the code

NSXMLParser is returned, and we need to parse it ourselves

This is required if the data returned is neither JSON nor XML

manager.responseSerializer = [AFHTTPResponseSerializer serializer];Copy the code

The AFN accepts three default ContentTypes




ContentType

If the server returns a ContentType that is not one of these three, we need to set it

manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];Copy the code

You can also directly add AFN source code (not recommended, this way is more covert, when the update AFN here will restore, problems are more difficult to find)




Just add it

3. Download files

// 1. Create a manager AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; / / 2. Create a request object NSURL * url = [NSURL URLWithString: @ "http://120.25.226.186:32812/resources/images/minion_03.png"); NSURLRequest *request =[NSURLRequest requestWithURL:url]; / / 3. Download file NSURLSessionDownloadTask * downloadTask = [manager downloadTaskWithRequest: request progress: ^ (NSProgress * _Nonnull downloadProgress) {/ / downloadProgress.com pletedUnitCount current download size / / downloadProgress totalUnitCount total size NSLog (@ "% f", * downloadProgress.com 1.0 pletedUnitCount/downloadProgress totalUnitCount);  } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull Response) {// targetPath temporary storage address NSLog(@"targetPath:%@",targetPath);  NSString *path =[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];  NSString *filePath = [path stringByAppendingPathComponent:response.suggestedFilename];  NSURL *url = [NSURL fileURLWithPath:filePath]; NSLog(@"path:%@",filePath); // Return the url we want to store // response header return URL;  } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {// Response response header // filePath NSLog(@"filePath:%@",filePath);}]; // Start [downloadTask Resume] manually.Copy the code

Note: 1. To download files, obtain the NSURLSessionDownloadTask object and start it manually. 2. The first block: downloadProgress has two attributes completedUnitCount (the size of the file downloaded) and totalUnitCount (the total size of the file). 3. Second block: You need to return a URL indicating where you want the file to be stored. TargetPath: temporary storage address in TMP temporary file. 4. Third block: call after downloading. Response: Response header. FilePath: File storage address, which is the same address as the URL returned in the second block

4. Upload files

For file upload, it is much easier to use AFN, and we do not need to concatenate the request body and request file parameters. AFN has already concatenated the request body and request file parameters for us

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; Nsstrings * url = @ "http://120.25.226.186:32812/upload"; [manager POST: url parameters: nil constructingBodyWithBlock: ^ (id _Nonnull formData) {/ / formData UIImage * image to upload data =[UIImage imageNamed:@"123"]; NSData *data =UIImagePNGRepresentation(image); // Method 1 /** data: upload file binary data Name: interface name fileName: what is the name of the file after uploading it to the server mineType: upload file type, Can upload any binary mineType. * / [formData appendPartWithFileData: data name: @ "file fileName:" @ "123 PNG" mimeType: @ "image/PNG"]. // method 2 /** data: upload file binary data name: interface name * / and automatically obtain the types [formData appendPartWithFormData: data name: @ "file"]. } progress:^(NSProgress * _Nonnull uploadProgress) {// uploadProgress} success:^(NSURLSessionDataTask * _Nonnull task, Id _Nullable responseObject) {NSLog(@" upload successful "); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {NSLog(@" upload failed ");}];Copy the code

Method 2: formData directly add url

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; Nsstrings * url = @ "http://120.25.226.186:32812/upload"; [manager POST: url parameters: nil constructingBodyWithBlock: ^ (id _Nonnull formData) {/ / / / formData will upload data direct url NSURL  *url =[NSURL fileURLWithPath:@"/Users/yangboxing/Desktop/Snip20160905_7.png"]; / / method [formData appendPartWithFileURL: url name: @ "file fileName:" @ "hhaha. PNG" mimeType: @ "image/PNG" error: nil]; // method 2 /** This method automatically intercepts the file name of the last block of the URL as the file name to upload to the server. It also automatically retrieves the mimeType. If you cannot retrieve the mimeType, use @"application/octet-stream" to indicate any binary data. We can also use this when we don't care about file types.  */ [formData appendPartWithFileURL:url name:@"file" error:nil]; } progress:^(NSProgress * _Nonnull uploadProgress) {// uploadProgress} success:^(NSURLSessionDataTask * _Nonnull task, Id _Nullable responseObject) {NSLog(@" upload successful "); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {NSLog(@" upload failed ");}];Copy the code

Note: mimeType is the type of the file. We can search for mimeType, or we can send a request to get mineType

// get mimeType -(NSString *)connectSync:(NSString *)path {//1. NSURL *url = [NSURL fileURLWithPath:path]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSHTTPURLResponse *res = nil; [NSURLConnection sendSynchronousRequest:request returningResponse:&res error:nil]; NSLog(@"%@",res.MIMEType); return res.MIMEType; }Copy the code

We through [formData appendPartWithFileURL: url name: @ “file” error: nil]; How does AFN get the mimeType




Obtain the file name and mimeType

Inside a method




The mimeType for

So we can copy the mimeType directly from AFN in the future.

5. Check the AFN network status

State of the network are detected using AFN is very simple, and can continue to monitor the network state, when the network status, at the time of change will call setReachabilityStatusChangeBlock method

AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager]; / * AFNetworkReachabilityStatusUnknown = 1, unknown AFNetworkReachabilityStatusNotReachable = 0, No Internet AFNetworkReachabilityStatusReachableViaWWAN = 1, cellular traffic AFNetworkReachabilityStatusReachableViaWiFi = 2, Wireless * / / / to monitor the change of network state [manager setReachabilityStatusChangeBlock: ^ (AFNetworkReachabilityStatus status) {switch (status) { Case AFNetworkReachabilityStatusUnknown: NSLog (@ "unknown"); break; case AFNetworkReachabilityStatusNotReachable: NSLog (@ "no network"); break; case AFNetworkReachabilityStatusReachableViaWWAN: NSLog (@ "3 g"); break; case AFNetworkReachabilityStatusReachableViaWiFi: NSLog (@ "wireless"); break; default: break;}}]; // Enable [Manager startMonitoring];Copy the code

6. The AFN sends a request to HTTPS.

We know that HTTPS adds SSL to HTTP, which relies on certificates to verify the identity of the server and to encrypt communication between the browser and the server. When using NSURLSession to send a request to HTTPS, you need to trust the server and create a certificate to return to the server in the NSURLSessionDataDelegate proxy method didReceiveChallenge. AFN encapsulates this very well and does this for us internally, so sending a request to HTTPS is the same as sending a request to HTTP. Let’s look at the method of AFN internal encapsulation




AFN internal encapsulation method

So when we use NSURLSession to send a request to HTTPS, we can just copy it and modify it a little bit

-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler { NSLog(@"--didReceiveChallenge--%@",challenge.protectionSpace); / * NSURLSessionAuthChallengeUseCredential = 0, use NSURLSessionAuthChallengePerformDefaultHandling = 1, NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2 (default), ignored (request) NSURLSessionAuthChallengeRejectProtectionSpace = 3, Ignore (next to ask) * / / / NSURLAuthenticationMethodServerTrust server trust the if ([challenge. ProtectionSpace. AuthenticationMethod IsEqualToString: NSURLAuthenticationMethodServerTrust]) {/ / create certificate NSURLCredential * credentoal = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,credentoal); }}Copy the code

3. To summarize

We usually use AFN will he wrapped in a utility class, make utility class a middle tier, for convenient management of the code, and we use later when the AFN update or we want to change the network request third party libraries, directly change the tools is ok, don’t have to change the online request method in other classes, This makes it easier to maintain code in the future.

For the basic knowledge of network request, see ios-Network Programming (1)HTTP protocol, ios-Network Programming (2) File Upload and Breakpoint Offline Download.

✨ this article draws lessons from many predecessors’ articles, if there is any wrong place please correct, welcome everyone to exchange and learn xx_cc.