1
This commit is contained in:
@@ -26,7 +26,8 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
||||
if (self = [super init]) {
|
||||
_enabled = NO; // 键盘扩展默认无网络能力,需外部显式开启
|
||||
_timeout = 10.0;
|
||||
_defaultHeaders = @{ @"Accept": @"application/json" };
|
||||
// 默认接受任意类型,避免下载图片/二进制被服务端基于 Accept 拒绝
|
||||
_defaultHeaders = @{ @"Accept": @"*/*" };
|
||||
// 设置基础域名,路径可相对该地址拼接
|
||||
_baseURL = [NSURL URLWithString:KB_BASE_URL];
|
||||
}
|
||||
@@ -45,10 +46,15 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
||||
// 使用 AFHTTPRequestSerializer 生成带参数与头的请求
|
||||
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
|
||||
serializer.timeoutInterval = self.timeout;
|
||||
NSError *serror = nil;
|
||||
NSMutableURLRequest *req = [serializer requestWithMethod:@"GET"
|
||||
URLString:urlString
|
||||
parameters:parameters
|
||||
error:NULL];
|
||||
error:&serror];
|
||||
if (serror || !req) {
|
||||
if (completion) completion(nil, nil, serror ?: [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorInvalidURL userInfo:@{NSLocalizedDescriptionKey: @"无效的URL"}]);
|
||||
return nil;
|
||||
}
|
||||
[self applyHeaders:headers toMutableRequest:req contentType:nil];
|
||||
return [self startAFTaskWithRequest:req completion:completion];
|
||||
}
|
||||
@@ -109,7 +115,11 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
||||
// 响应先用原始数据返回,再按 Content-Type 解析 JSON(与原实现一致)
|
||||
self.manager.responseSerializer = [AFHTTPResponseSerializer serializer];
|
||||
NSURLSessionDataTask *task = [self.manager dataTaskWithRequest:req uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
|
||||
if (error) { if (completion) completion(nil, response, error); return; }
|
||||
// AFN 默认对非 2xx 的状态码返回 error;这里直接回调上层
|
||||
if (error) {
|
||||
if (completion) completion(nil, response, error);
|
||||
return;
|
||||
}
|
||||
NSData *data = (NSData *)responseObject;
|
||||
if (![data isKindOfClass:[NSData class]]) {
|
||||
if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorInvalidResponse userInfo:@{NSLocalizedDescriptionKey:@"无数据"}]);
|
||||
@@ -119,7 +129,19 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
||||
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
ct = ((NSHTTPURLResponse *)response).allHeaderFields[@"Content-Type"];
|
||||
}
|
||||
BOOL looksJSON = (ct && [ct.lowercaseString containsString:@"application/json"]);
|
||||
// 更宽松的 JSON 判定:Content-Type 里包含 json;或首字符是 { / [
|
||||
BOOL looksJSON = (ct && [[ct lowercaseString] containsString:@"json"]);
|
||||
if (!looksJSON) {
|
||||
// 内容嗅探(不依赖服务端声明)
|
||||
const unsigned char *bytes = data.bytes;
|
||||
NSUInteger len = data.length;
|
||||
for (NSUInteger i = 0; !looksJSON && i < len; i++) {
|
||||
unsigned char c = bytes[i];
|
||||
if (c == ' ' || c == '\n' || c == '\r' || c == '\t') continue;
|
||||
looksJSON = (c == '{' || c == '[');
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (looksJSON) {
|
||||
NSError *jsonErr = nil;
|
||||
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonErr];
|
||||
@@ -139,8 +161,7 @@ NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
||||
if (!_manager) {
|
||||
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration ephemeralSessionConfiguration];
|
||||
cfg.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
|
||||
cfg.timeoutIntervalForRequest = self.timeout;
|
||||
cfg.timeoutIntervalForResource = MAX(self.timeout, 30.0);
|
||||
// 不在会话级别设置超时,避免与 per-request 的 serializer.timeoutInterval 产生不一致
|
||||
if (@available(iOS 11.0, *)) { cfg.waitsForConnectivity = YES; }
|
||||
_manager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:cfg];
|
||||
// 默认不使用 JSON 解析器,保持原生数据,再按需解析
|
||||
|
||||
Reference in New Issue
Block a user