「OC」AFNetworking的简单使用

「OC」AFNetworking的简单使用

前言

在我们进行网络申请的时候,直接使用OC之中自带的NSURLNSURLRequestNSURLSession进行相关操作,还需要实现Task回调、调用resume。那对我们进行开发来说还是相对比较繁琐的,为了简化我们的网络请求,我们其实可以直接使用AFNetworking这个第三方库进行网络请求的操作(下文简称AFN)。

介绍

我们先来对AFNetworking的核心组件进行介绍

AFHTTPSessionManager:基于 NSURLSession 的管理类,用于发送网络请求和处理响应。AFHTTPSessionManager 是最常用的类,用于处理 HTTP 请求。

AFURLSessionManager:基于 NSURLSession,用于管理下载、上传等任务。

AFNetworkReachabilityManager:用于监控网络状态的变化。

处理响应格式

AFNetworking 可以自动解析响应的数据格式,常用的解析格式有 JSON、XML、和图片。

  • JSON 响应: 默认情况下,AFHTTPSessionManager 会将服务器返回的 JSON 自动解析为字典或数组。

    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    
  • XML 响应: 如果你的服务器返回 XML,你可以使用 AFXMLParserResponseSerializer

    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
    
  • 图片下载: AFNetworking 也支持图片下载,并且可以设置下载的图片缓存。

    manager.responseSerializer = [AFImageResponseSerializer serializer];
    

进行简单的GET操作

我们以天气预报的信息申请为例子,如果使用OC之中原生的网络请求,代码大致如下

// 用 NSString 创建 URL
NSString *urlString = @"https://devapi.qweather.com/v7/weather/now?location=101110101&key=487fcdf6fdc9401da0ac4c4df535f43d";
NSURL *url = [NSURL URLWithString:urlString];

// 创建 URLSession 对象
NSURLSession *session = [NSURLSession sharedSession];

// 创建 URLRequest 对其进行相关请求,这里使用 GET 方法
NSURLRequest *request = [NSURLRequest requestWithURL:url];

// 根据会话创建任务
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
  	//用block实现回调,处理接受的参数
    if (error) {
        NSLog(@"错误: %@", error);
        return;
    }

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
    if (httpResponse.statusCode >= 200 && httpResponse.statusCode < 300) {
        NSError *jsonError;
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
        if (jsonError) {
            NSLog(@"解析失败: %@", jsonError);
        } else {
            NSLog(@"数据如下: %@", json);
            // 在这里处理返回的数据
        }
    } else {
        NSLog(@"非法响应: %ld", (long)httpResponse.statusCode);
    }
}];

// 启动任务
[task resume];

如果我们引入AFNetworking库,那么代码就会被简化为以下内容

// 导入 AFNetworking
#import <AFNetworking/AFNetworking.h>

// 用 NSString 创建 URL
NSString *urlString = @"https://devapi.qweather.com/v7/weather/now?location=101110101&key=487fcdf6fdc9401da0ac4c4df535f43d";

// 使用 AFHTTPSessionManager 来管理请求
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

// 设置响应格式为 JSON
manager.responseSerializer = [AFJSONResponseSerializer serializer];

// 发起 GET 请求
[manager GET:urlString parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    // 请求成功,处理返回数据
    NSLog(@"数据如下: %@", responseObject);
    // 在这里处理返回的数据
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    // 请求失败,处理错误
    NSLog(@"错误: %@", error);
}];

我们可以看到,这个程序使用了AFNetworking之中的内容进行操作。其中,GET:parameters:headers:progress:success:failure: 方法是用于发送 GET 请求的基本 API。

responseObject 是返回的数据,AFNetworking 会自动解析 JSON。

添加请求头的GET操作

我们在进行网络请求的时候,有时候会需要用上请求头才能完成完整的网络请求,那我们需要在session的主体之中添加一个请求头。

如果使用OC原生的代码,那么操作还是很繁琐的,拿我们使用Spotify的艺术家申请,代码大致如下

- (void)getArtistInfo:(NSString *)artistID accessToken:(NSString *)accessToken {
    NSString *urlString = [NSString stringWithFormat:@"https://api.spotify.com/v1/artists/%@",artistID];
    NSURL *url = [NSURL URLWithString:urlString];
    
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"GET"];
    [request setValue:[NSString stringWithFormat:@"Bearer %@", accessToken] forHTTPHeaderField:@"Authorization"];
    
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"%@", error.localizedDescription);
            return;
        }
        
        NSError *jsonError;
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
        
        if (jsonError) {
            NSLog(@"%@", jsonError.localizedDescription);
            return;
        }
        Artist *art = [Artist yy_modelWithDictionary:json];
        NSLog(@"Artist Info:%@",json);
        NSLog(@"Artist Info: %ld", (long)art.followersTotal);
    }];
    
    [task resume];
}

接下来我们来看看,使用了AFNetworking

- (void)getArtistInfo:(NSString *)artistID accessToken:(NSString *)accessToken {
    NSString *urlString = [NSString stringWithFormat:@"https://api.spotify.com/v1/artists/%@", artistID];
    
    // 创建 AFHTTPSessionManager 实例
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    // 设置请求头
    [manager.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@", accessToken] forHTTPHeaderField:@"Authorization"];
    
    // 发起 GET 请求
    [manager GET:urlString parameters:nil headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        // 成功获取数据
        NSDictionary *json = (NSDictionary *)responseObject;
        Artist *art = [Artist yy_modelWithDictionary:json];
        
        NSLog(@"Artist Info: %@", json);
        NSLog(@"Artist Followers Total: %ld", (long)art.followersTotal);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        // 处理错误
        NSLog(@"%@", error.localizedDescription);
    }];
}

我们可以看到即使增加了请求头,在AFNetworking之中还是十分的方便的,我们只需要在manager之中的requestSerializer使用相关的方法设置它的请求头,再次调用GET的相关函数。

POST请求

学习完了如何使用AFN完成GET,接下来是网络请求不可或缺的POST请求的学习,下面我使用一个简单的POST函数来实现一个登陆注册的操作

- (void)loginWithUsername:(NSString *)username password:(NSString *)password {
    NSString *urlString = @"https://api.example.com/login";
    
    // 创建 AFHTTPSessionManager 实例
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    // 请求参数
    NSDictionary *parameters = @{@"username": username, @"password": password};
    
    // 发起 POST 请求
    [manager POST:urlString parameters:parameters headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        // 成功获取响应数据
        NSLog(@"%@", responseObject);
        
        // 在这里可以解析响应数据,比如存储的Token
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        // 处理失败
        NSLog(@"%@", error.localizedDescription);
    }];
}

可以看到我们实现POST操作和GET操作本质上没有什么特别大的的区别,POST的请求只是讲包装后的字典发送到对应的URL地址,惊醒对应的验证。

使用POST操作上传图片

我们使用POST之中上传图片作为例子,模拟如何进文件的上传

#import <AFNetworking/AFNetworking.h>

- (void)uploadImageWithURL:(NSString *)urlString
                 imageData:(NSData *)imageData
                parameters:(NSDictionary *)parameters
              successBlock:(void (^)(id responseObject))successBlock
              failureBlock:(void (^)(NSError *error))failureBlock {
    
    // 创建请求管理器
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    // 设置请求的 `Content-Type` 为 `multipart/form-data`
    [manager POST:urlString parameters:parameters headers:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        
        // 将二进制图像数据添加到 `formData`
        [formData appendPartWithFileData:imageData
                                    name:@"file" // 文件字段名,服务器接收的 key
                                fileName:@"image.jpg" // 文件名,可以随意
                                mimeType:@"image/jpeg"]; // MIME 类型,取决于文件类型
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
        
        // 上传进度处理 (可选)
        NSLog(@"Upload Progress: %.2f%%", 100.0 * uploadProgress.fractionCompleted);
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        // 请求成功,处理服务器返回的数据
        NSLog(@"%@", responseObject);
        if (successBlock) {
            successBlock(responseObject);
        }
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        // 请求失败,处理错误
        NSLog(@"%@", error);
        if (failureBlock) {
            failureBlock(error);
        }
    }];
}

这里我们使用两个回调的block进行对应的成功和失败的操作,可以确保我们在获取到对应信息之后,再进行接下来的相关操作

NSString *url = @"https://example.com/upload";
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"exampleImage"], 0.9); // 将图片转成NSData格式 即二进制格式
NSDictionary *parameters = @{@"userId": @"12345", @"description": @"Profile Image"};

[self uploadImageWithURL:url imageData:imageData parameters:parameters successBlock:^(id responseObject) {
    NSLog(@"Success response: %@", responseObject);
} failureBlock:^(NSError *error) {
    NSLog(@"Failed with error: %@", error.localizedDescription);
}];

对于这个方法**appendPartWithFileData:name:fileName:mimeType:**:

  • fileData: 你要上传的文件的二进制数据(如图片的 NSData)。
  • name: 服务器端接收文件的字段名,通常是 "file" 或自定义字段。
  • fileName: 上传时文件的名字,可以指定任何合适的文件名,比如 "image.jpg"
  • mimeType: 上传文件的 MIME 类型,比如 "image/jpeg""application/pdf"

要是是其他的文件,比如PDF或者MP3格式的,需要调整 fileNamemimeType。例如:

  • PDF: @"application/pdf"
  • MP3: @"audio/mpeg"

NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"profile.jpg"], 0.8);将图片文件转换为 JPEG 格式的二进制数据(NSData),CGFloat compressionQuality: 这是 JPEG 的压缩质量参数,范围是 0.01.0,其中 1.0 表示最高质量,0.0 表示最低质量(高压缩)。通常,0.70.9 的压缩比可以保持较好的图片质量,同时减少文件大小。

用单例进行网络申请

在进行网络申请的时候,我们可以使用一个AFN实现一个单例类,在项目中使用 AFNetworking 的单例进行网络请求,可以创建一个 AFHTTPSessionManager 的单例类。这有助于网络请求在整个应用中保持统一的配置,比如通用的请求头、超时时间等。这就可以用上我们先前的GCD之中的Once函数。

// NetworkManager.h
#import <AFNetworking/AFNetworking.h>

@interface NetworkManager : AFHTTPSessionManager

+ (instancetype)sharedManager;

@end

.m文件

// NetworkManager.m
#import "NetworkManager.h"

@implementation NetworkManager

+ (instancetype)sharedManager {
    static NetworkManager *sharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 初始化 AFHTTPSessionManager 并进行一些全局配置
        sharedManager = [[self alloc] initWithBaseURL:[NSURL URLWithString:@"https://api.yourserver.com/"]];
        
        // 例如,设置请求的超时时间
        sharedManager.requestSerializer.timeoutInterval = 30;
        
        // 可以设置请求的序列化格式(默认是JSON)
        sharedManager.requestSerializer = [AFJSONRequestSerializer serializer];
        
        // 可以设置响应的序列化格式(默认是JSON)
        sharedManager.responseSerializer = [AFJSONResponseSerializer serializer];
    });
    
    return sharedManager;
}

@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值