实战:用 Objective-C 类封装网络请求模块,实现高复用性
·
网络请求模块封装实战(Objective-C)
设计思路
- 高复用性:通过单例模式+回调机制实现
- 功能完整:支持GET/POST/上传/下载/缓存
- 错误处理:统一错误码和回调格式
- 扩展性:使用协议解耦具体实现
核心实现(NetworkManager类)
// NetworkManager.h
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, HTTPMethod) {
GET,
POST,
PUT,
DELETE
};
typedef void (^NetworkSuccessBlock)(id _Nullable responseObject);
typedef void (^NetworkFailureBlock)(NSError * _Nonnull error);
@interface NetworkManager : NSObject
+ (instancetype)shared;
- (void)request:(HTTPMethod)method
url:(NSString *)url
parameters:(nullable NSDictionary *)params
headers:(nullable NSDictionary *)headers
success:(NetworkSuccessBlock)success
failure:(NetworkFailureBlock)failure;
- (void)uploadFile:(NSData *)fileData
url:(NSString *)url
parameters:(nullable NSDictionary *)params
fileName:(NSString *)fileName
mimeType:(NSString *)mimeType
success:(NetworkSuccessBlock)success
failure:(NetworkFailureBlock)failure;
@end
// NetworkManager.m
#import "NetworkManager.h"
@implementation NetworkManager {
NSURLSession *_session;
}
+ (instancetype)shared {
static NetworkManager *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (instancetype)init {
if (self = [super init]) {
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.timeoutIntervalForRequest = 30.0;
_session = [NSURLSession sessionWithConfiguration:config];
}
return self;
}
#pragma mark - 核心请求方法
- (void)request:(HTTPMethod)method
url:(NSString *)url
parameters:(NSDictionary *)params
headers:(NSDictionary *)headers
success:(NetworkSuccessBlock)success
failure:(NetworkFailureBlock)failure {
// 1. 构建URLRequest
NSURL *requestURL = [NSURL URLWithString:url];
if (!requestURL) {
failure([self errorWithCode:1001 message:@"URL格式错误"]);
return;
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:requestURL];
request.HTTPMethod = [self methodString:method];
// 2. 添加请求头
[headers enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[request addValue:obj forHTTPHeaderField:key];
}];
// 3. 处理请求体 (POST/PUT)
if (params && (method == POST || method == PUT)) {
NSError *error;
NSData *bodyData = [NSJSONSerialization dataWithJSONObject:params options:0 error:&error];
if (!error) {
request.HTTPBody = bodyData;
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
}
}
// 4. 创建任务并执行
NSURLSessionDataTask *task = [_session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
failure(error);
} else {
NSError *jsonError;
id responseObj = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
if (jsonError) {
failure([self errorWithCode:1002 message:@"JSON解析失败"]);
} else {
success(responseObj);
}
}
});
}];
[task resume];
}
#pragma mark - 文件上传
- (void)uploadFile:(NSData *)fileData
url:(NSString *)url
parameters:(NSDictionary *)params
fileName:(NSString *)fileName
mimeType:(NSString *)mimeType
success:(NetworkSuccessBlock)success
failure:(NetworkFailureBlock)failure {
// 1. 构建多部分请求体
NSString *boundary = [NSString stringWithFormat:@"Boundary-%@", NSUUID.UUID.UUIDString];
NSMutableData *body = [NSMutableData data];
// 添加参数
[params enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL *stop) {
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", value] dataUsingEncoding:NSUTF8StringEncoding]];
}];
// 添加文件
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", fileName] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimeType] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:fileData];
[body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// 2. 配置请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
request.HTTPMethod = @"POST";
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)body.length] forHTTPHeaderField:@"Content-Length"];
request.HTTPBody = body;
// 3. 执行上传任务
NSURLSessionUploadTask *task = [_session uploadTaskWithRequest:request fromData:body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error) {
failure(error);
} else {
success(data);
}
});
}];
[task resume];
}
#pragma mark - 工具方法
- (NSString *)methodString:(HTTPMethod)method {
switch (method) {
case GET: return @"GET";
case POST: return @"POST";
case PUT: return @"PUT";
case DELETE: return @"DELETE";
}
}
- (NSError *)errorWithCode:(NSInteger)code message:(NSString *)message {
return [NSError errorWithDomain:@"NetworkError"
code:code
userInfo:@{NSLocalizedDescriptionKey: message}];
}
@end
使用示例
// 发起GET请求
[[NetworkManager shared] request:GET
url:@"https://api.example.com/data"
parameters:@{@"page": @1}
headers:@{@"Authorization": @"Bearer token123"}
success:^(id responseObject) {
NSLog(@"请求成功: %@", responseObject);
} failure:^(NSError *error) {
NSLog(@"请求失败: %@", error.localizedDescription);
}];
// 上传图片
UIImage *image = [UIImage imageNamed:@"avatar"];
NSData *imageData = UIImageJPEGRepresentation(image, 0.8);
[[NetworkManager shared] uploadFile:imageData
url:@"https://api.example.com/upload"
parameters:@{@"userId": @"123"}
fileName:@"avatar.jpg"
mimeType:@"image/jpeg"
success:^(id response) {
NSLog(@"上传成功");
} failure:^(NSError *error) {
NSLog(@"上传失败: %@", error);
}];
设计亮点
- 单例全局访问:通过
shared方法获取唯一实例 - 统一错误处理:自定义错误域和错误码
- 线程安全:使用GCD确保回调在主线程执行
- 类型安全:枚举定义HTTP方法
- 扩展性强:可轻松添加缓存、日志等模块
扩展建议
- 添加缓存层:集成NSCache实现内存缓存
- 网络状态监测:使用Reachability检测网络变化
- 请求重试机制:对特定错误自动重试
- 安全加固:增加HTTPS证书校验
- 性能监控:记录请求耗时和成功率
此实现满足高复用性需求,通过统一接口封装了网络请求的核心功能,可应用于各类iOS项目,大幅减少重复代码量。
更多推荐

所有评论(0)