添加图片库、封装
This commit is contained in:
@@ -33,10 +33,13 @@
|
|||||||
04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D42EB1EA16007BD342 /* BaseCell.m */; };
|
04FC95D82EB1EA16007BD342 /* BaseCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95D42EB1EA16007BD342 /* BaseCell.m */; };
|
||||||
04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95DC2EB202A3007BD342 /* KBGuideVC.m */; };
|
04FC95DD2EB202A3007BD342 /* KBGuideVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95DC2EB202A3007BD342 /* KBGuideVC.m */; };
|
||||||
04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95E42EB220B5007BD342 /* UIColor+Extension.m */; };
|
04FC95E52EB220B5007BD342 /* UIColor+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95E42EB220B5007BD342 /* UIColor+Extension.m */; };
|
||||||
|
04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95E72EB23B67007BD342 /* KBNetworkManager.m */; };
|
||||||
04FC97002EB30A00007BD342 /* KBGuideTopCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC96FF2EB30A00007BD342 /* KBGuideTopCell.m */; };
|
04FC97002EB30A00007BD342 /* KBGuideTopCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC96FF2EB30A00007BD342 /* KBGuideTopCell.m */; };
|
||||||
04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97022EB30A00007BD342 /* KBGuideKFCell.m */; };
|
04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97022EB30A00007BD342 /* KBGuideKFCell.m */; };
|
||||||
04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97052EB30A00007BD342 /* KBGuideUserCell.m */; };
|
04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97052EB30A00007BD342 /* KBGuideUserCell.m */; };
|
||||||
04FC97092EB31B14007BD342 /* KBHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97082EB31B14007BD342 /* KBHUD.m */; };
|
04FC97092EB31B14007BD342 /* KBHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC97082EB31B14007BD342 /* KBHUD.m */; };
|
||||||
|
04FC970E2EB334F8007BD342 /* UIImageView+KBWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC970B2EB334F8007BD342 /* UIImageView+KBWebImage.m */; };
|
||||||
|
04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC970D2EB334F8007BD342 /* KBWebImageManager.m */; };
|
||||||
7A36414DFDA5BEC9B7D2E318 /* Pods_CustomKeyboard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */; };
|
7A36414DFDA5BEC9B7D2E318 /* Pods_CustomKeyboard.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */; };
|
||||||
A1B2C3D42EB0A0A100000001 /* KBFunctionTagCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D32EB0A0A100000001 /* KBFunctionTagCell.m */; };
|
A1B2C3D42EB0A0A100000001 /* KBFunctionTagCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3D32EB0A0A100000001 /* KBFunctionTagCell.m */; };
|
||||||
A1B2C3E22EB0C0A100000001 /* KBNetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3E12EB0C0A100000001 /* KBNetworkManager.m */; };
|
A1B2C3E22EB0C0A100000001 /* KBNetworkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C3E12EB0C0A100000001 /* KBNetworkManager.m */; };
|
||||||
@@ -119,6 +122,8 @@
|
|||||||
04FC95DC2EB202A3007BD342 /* KBGuideVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideVC.m; sourceTree = "<group>"; };
|
04FC95DC2EB202A3007BD342 /* KBGuideVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideVC.m; sourceTree = "<group>"; };
|
||||||
04FC95E32EB220B5007BD342 /* UIColor+Extension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIColor+Extension.h"; sourceTree = "<group>"; };
|
04FC95E32EB220B5007BD342 /* UIColor+Extension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIColor+Extension.h"; sourceTree = "<group>"; };
|
||||||
04FC95E42EB220B5007BD342 /* UIColor+Extension.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIColor+Extension.m"; sourceTree = "<group>"; };
|
04FC95E42EB220B5007BD342 /* UIColor+Extension.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIColor+Extension.m"; sourceTree = "<group>"; };
|
||||||
|
04FC95E62EB23B67007BD342 /* KBNetworkManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBNetworkManager.h; sourceTree = "<group>"; };
|
||||||
|
04FC95E72EB23B67007BD342 /* KBNetworkManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBNetworkManager.m; sourceTree = "<group>"; };
|
||||||
04FC96FE2EB30A00007BD342 /* KBGuideTopCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideTopCell.h; sourceTree = "<group>"; };
|
04FC96FE2EB30A00007BD342 /* KBGuideTopCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideTopCell.h; sourceTree = "<group>"; };
|
||||||
04FC96FF2EB30A00007BD342 /* KBGuideTopCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideTopCell.m; sourceTree = "<group>"; };
|
04FC96FF2EB30A00007BD342 /* KBGuideTopCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideTopCell.m; sourceTree = "<group>"; };
|
||||||
04FC97012EB30A00007BD342 /* KBGuideKFCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideKFCell.h; sourceTree = "<group>"; };
|
04FC97012EB30A00007BD342 /* KBGuideKFCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBGuideKFCell.h; sourceTree = "<group>"; };
|
||||||
@@ -127,6 +132,10 @@
|
|||||||
04FC97052EB30A00007BD342 /* KBGuideUserCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideUserCell.m; sourceTree = "<group>"; };
|
04FC97052EB30A00007BD342 /* KBGuideUserCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBGuideUserCell.m; sourceTree = "<group>"; };
|
||||||
04FC97072EB31B14007BD342 /* KBHUD.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBHUD.h; sourceTree = "<group>"; };
|
04FC97072EB31B14007BD342 /* KBHUD.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBHUD.h; sourceTree = "<group>"; };
|
||||||
04FC97082EB31B14007BD342 /* KBHUD.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBHUD.m; sourceTree = "<group>"; };
|
04FC97082EB31B14007BD342 /* KBHUD.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBHUD.m; sourceTree = "<group>"; };
|
||||||
|
04FC970A2EB334F8007BD342 /* UIImageView+KBWebImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImageView+KBWebImage.h"; sourceTree = "<group>"; };
|
||||||
|
04FC970B2EB334F8007BD342 /* UIImageView+KBWebImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+KBWebImage.m"; sourceTree = "<group>"; };
|
||||||
|
04FC970C2EB334F8007BD342 /* KBWebImageManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBWebImageManager.h; sourceTree = "<group>"; };
|
||||||
|
04FC970D2EB334F8007BD342 /* KBWebImageManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBWebImageManager.m; sourceTree = "<group>"; };
|
||||||
2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CustomKeyboard.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
2C1092FB2B452F95B15D4263 /* Pods_CustomKeyboard.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CustomKeyboard.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
51FE7C4C42C2255B3C1C4128 /* Pods-keyBoard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-keyBoard.release.xcconfig"; path = "Target Support Files/Pods-keyBoard/Pods-keyBoard.release.xcconfig"; sourceTree = "<group>"; };
|
51FE7C4C42C2255B3C1C4128 /* Pods-keyBoard.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-keyBoard.release.xcconfig"; path = "Target Support Files/Pods-keyBoard/Pods-keyBoard.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
727EC7532EAF848B00B36487 /* keyBoard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = keyBoard.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
727EC7532EAF848B00B36487 /* keyBoard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = keyBoard.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -338,6 +347,7 @@
|
|||||||
04FC95BF2EB1E3B1007BD342 /* Class */ = {
|
04FC95BF2EB1E3B1007BD342 /* Class */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
04FC95E82EB23B67007BD342 /* Network */,
|
||||||
04FC95E22EB2208F007BD342 /* Categories */,
|
04FC95E22EB2208F007BD342 /* Categories */,
|
||||||
04FC95E12EB20AD1007BD342 /* Guard */,
|
04FC95E12EB20AD1007BD342 /* Guard */,
|
||||||
04FC95C62EB1E4AB007BD342 /* Base */,
|
04FC95C62EB1E4AB007BD342 /* Base */,
|
||||||
@@ -429,12 +439,25 @@
|
|||||||
children = (
|
children = (
|
||||||
04FC95E32EB220B5007BD342 /* UIColor+Extension.h */,
|
04FC95E32EB220B5007BD342 /* UIColor+Extension.h */,
|
||||||
04FC95E42EB220B5007BD342 /* UIColor+Extension.m */,
|
04FC95E42EB220B5007BD342 /* UIColor+Extension.m */,
|
||||||
|
04FC970A2EB334F8007BD342 /* UIImageView+KBWebImage.h */,
|
||||||
|
04FC970B2EB334F8007BD342 /* UIImageView+KBWebImage.m */,
|
||||||
|
04FC970C2EB334F8007BD342 /* KBWebImageManager.h */,
|
||||||
|
04FC970D2EB334F8007BD342 /* KBWebImageManager.m */,
|
||||||
04FC97072EB31B14007BD342 /* KBHUD.h */,
|
04FC97072EB31B14007BD342 /* KBHUD.h */,
|
||||||
04FC97082EB31B14007BD342 /* KBHUD.m */,
|
04FC97082EB31B14007BD342 /* KBHUD.m */,
|
||||||
);
|
);
|
||||||
path = Categories;
|
path = Categories;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
04FC95E82EB23B67007BD342 /* Network */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
04FC95E62EB23B67007BD342 /* KBNetworkManager.h */,
|
||||||
|
04FC95E72EB23B67007BD342 /* KBNetworkManager.m */,
|
||||||
|
);
|
||||||
|
path = Network;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
2C53A0856097DCFBE7B55649 /* Pods */ = {
|
2C53A0856097DCFBE7B55649 /* Pods */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -615,10 +638,14 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-keyBoard/Pods-keyBoard-frameworks.sh\"\n";
|
||||||
@@ -672,6 +699,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
04FC95E92EB23B67007BD342 /* KBNetworkManager.m in Sources */,
|
||||||
04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */,
|
04FC95D22EB1E7AE007BD342 /* MyVC.m in Sources */,
|
||||||
043FBCD22EAF97630036AFE1 /* KBPermissionViewController.m in Sources */,
|
043FBCD22EAF97630036AFE1 /* KBPermissionViewController.m in Sources */,
|
||||||
04C6EABE2EAF86530089C901 /* AppDelegate.m in Sources */,
|
04C6EABE2EAF86530089C901 /* AppDelegate.m in Sources */,
|
||||||
@@ -684,6 +712,8 @@
|
|||||||
04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */,
|
04FC97032EB30A00007BD342 /* KBGuideKFCell.m in Sources */,
|
||||||
04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */,
|
04FC97062EB30A00007BD342 /* KBGuideUserCell.m in Sources */,
|
||||||
04FC97092EB31B14007BD342 /* KBHUD.m in Sources */,
|
04FC97092EB31B14007BD342 /* KBHUD.m in Sources */,
|
||||||
|
04FC970E2EB334F8007BD342 /* UIImageView+KBWebImage.m in Sources */,
|
||||||
|
04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */,
|
||||||
04FC95CF2EB1E7A1007BD342 /* HomeVC.m in Sources */,
|
04FC95CF2EB1E7A1007BD342 /* HomeVC.m in Sources */,
|
||||||
04C6EABF2EAF86530089C901 /* main.m in Sources */,
|
04C6EABF2EAF86530089C901 /* main.m in Sources */,
|
||||||
04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */,
|
04FC95CC2EB1E780007BD342 /* BaseTabBarController.m in Sources */,
|
||||||
|
|||||||
31
keyBoard/Class/Categories/KBWebImageManager.h
Normal file
31
keyBoard/Class/Categories/KBWebImageManager.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// KBWebImageManager.h
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
// SDWebImage 的二次封装:全局配置、预取、缓存管理
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface KBWebImageManager : NSObject
|
||||||
|
|
||||||
|
/// 预取一组图片
|
||||||
|
+ (void)prefetchURLs:(NSArray<id> *)urlList
|
||||||
|
progress:(void(^_Nullable)(NSUInteger finished, NSUInteger total))progress
|
||||||
|
completed:(void(^_Nullable)(NSUInteger finished, NSUInteger skipped))completed;
|
||||||
|
|
||||||
|
/// 异步计算磁盘缓存大小(字节)
|
||||||
|
+ (void)calculateDiskSize:(void(^)(NSUInteger bytes))completion;
|
||||||
|
|
||||||
|
/// 清理内存+磁盘缓存
|
||||||
|
+ (void)clearAllCache:(void(^_Nullable)(void))completion;
|
||||||
|
|
||||||
|
/// 设置全局 HTTP Header(如鉴权 Token)
|
||||||
|
+ (void)setHTTPHeaderValue:(nullable NSString *)value forKey:(NSString *)field;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
51
keyBoard/Class/Categories/KBWebImageManager.m
Normal file
51
keyBoard/Class/Categories/KBWebImageManager.m
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// KBWebImageManager.m
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "KBWebImageManager.h"
|
||||||
|
#import <SDWebImage/SDWebImage.h>
|
||||||
|
|
||||||
|
static inline NSURL *_KBURL(id url) {
|
||||||
|
if (!url) return nil;
|
||||||
|
if ([url isKindOfClass:NSURL.class]) return url;
|
||||||
|
if ([url isKindOfClass:NSString.class]) return [NSURL URLWithString:(NSString *)url];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation KBWebImageManager
|
||||||
|
|
||||||
|
+ (void)prefetchURLs:(NSArray<id> *)urlList
|
||||||
|
progress:(void(^)(NSUInteger finished, NSUInteger total))progress
|
||||||
|
completed:(void(^)(NSUInteger finished, NSUInteger skipped))completed {
|
||||||
|
NSMutableArray<NSURL *> *urls = [NSMutableArray arrayWithCapacity:urlList.count];
|
||||||
|
for (id u in urlList) { NSURL *nu = _KBURL(u); if (nu) [urls addObject:nu]; }
|
||||||
|
[[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:urls progress:^(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls) {
|
||||||
|
if (progress) progress(noOfFinishedUrls, noOfTotalUrls);
|
||||||
|
} completed:^(NSUInteger finishedCount, NSUInteger skippedCount) {
|
||||||
|
if (completed) completed(finishedCount, skippedCount);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)calculateDiskSize:(void(^)(NSUInteger bytes))completion {
|
||||||
|
[[SDImageCache sharedImageCache] calculateSizeWithCompletionBlock:^(NSUInteger fileCount, NSUInteger totalSize) {
|
||||||
|
if (completion) completion(totalSize);
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)clearAllCache:(void(^)(void))completion {
|
||||||
|
SDImageCache *cache = SDImageCache.sharedImageCache;
|
||||||
|
[cache clearMemory];
|
||||||
|
[cache clearDiskOnCompletion:^{ if (completion) completion(); }];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void)setHTTPHeaderValue:(NSString *)value forKey:(NSString *)field {
|
||||||
|
if (value.length == 0) {
|
||||||
|
[[SDWebImageDownloader sharedDownloader] setValue:nil forHTTPHeaderField:field];
|
||||||
|
} else {
|
||||||
|
[[SDWebImageDownloader sharedDownloader] setValue:value forHTTPHeaderField:field];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
49
keyBoard/Class/Categories/UIImageView+KBWebImage.h
Normal file
49
keyBoard/Class/Categories/UIImageView+KBWebImage.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// UIImageView+KBWebImage.h
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
// 在 SDWebImage 基础上的便捷封装:
|
||||||
|
// - 统一默认 options(失败重试、后台续传、降采样等)
|
||||||
|
// - 支持按视图大小缩略解码,减少内存占用
|
||||||
|
// - 常用形状:普通、圆角、头像圆形
|
||||||
|
// - 支持占位图、渐隐动画、取消下载
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface UIImageView (KBWebImage)
|
||||||
|
|
||||||
|
/// 简单加载(默认 options,自动渐隐)
|
||||||
|
- (void)kb_setImageURL:(nullable id)url placeholder:(nullable UIImage *)placeholder;
|
||||||
|
|
||||||
|
/// 自定义 options
|
||||||
|
- (void)kb_setImageURL:(nullable id)url
|
||||||
|
placeholder:(nullable UIImage *)placeholder
|
||||||
|
options:(NSUInteger)options;
|
||||||
|
|
||||||
|
/// 按视图大小缩略解码(推荐:内存友好)。若视图尚未布局,可传入 `targetSize` 期望像素尺寸(点×scale)。
|
||||||
|
- (void)kb_setImageURL:(nullable id)url
|
||||||
|
placeholder:(nullable UIImage *)placeholder
|
||||||
|
thumbnailToFit:(BOOL)thumbnailToFit
|
||||||
|
targetSize:(CGSize)targetPixelSize;
|
||||||
|
|
||||||
|
/// 圆角图(在解码阶段裁圆角,避免离屏开销)
|
||||||
|
- (void)kb_setImageURL:(nullable id)url
|
||||||
|
placeholder:(nullable UIImage *)placeholder
|
||||||
|
cornerRadius:(CGFloat)radius
|
||||||
|
corners:(UIRectCorner)corners
|
||||||
|
borderWidth:(CGFloat)borderWidth
|
||||||
|
borderColor:(nullable UIColor *)borderColor;
|
||||||
|
|
||||||
|
/// 头像:自动按最短边裁成圆形(若视图尚未布局,会使用当前 bounds 估算)
|
||||||
|
- (void)kb_setAvatarURL:(nullable id)url placeholder:(nullable UIImage *)placeholder;
|
||||||
|
|
||||||
|
/// 取消当前图的下载
|
||||||
|
- (void)kb_cancelImageLoad;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
142
keyBoard/Class/Categories/UIImageView+KBWebImage.m
Normal file
142
keyBoard/Class/Categories/UIImageView+KBWebImage.m
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
//
|
||||||
|
// UIImageView+KBWebImage.m
|
||||||
|
// keyBoard
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "UIImageView+KBWebImage.h"
|
||||||
|
#import <SDWebImage/SDWebImage.h>
|
||||||
|
|
||||||
|
// 默认下载配置:失败重试、后台续传、降采样、大图优先级
|
||||||
|
static inline SDWebImageOptions KBWebImageDefaultOptions(void) {
|
||||||
|
return SDWebImageRetryFailed |
|
||||||
|
SDWebImageContinueInBackground |
|
||||||
|
SDWebImageHighPriority |
|
||||||
|
SDWebImageScaleDownLargeImages |
|
||||||
|
SDWebImageProgressiveLoad; // 渐进式
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline NSURL *_KBURL(id url) {
|
||||||
|
if (!url) return nil;
|
||||||
|
if ([url isKindOfClass:NSURL.class]) return url;
|
||||||
|
if ([url isKindOfClass:NSString.class]) return [NSURL URLWithString:(NSString *)url];
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@implementation UIImageView (KBWebImage)
|
||||||
|
|
||||||
|
- (void)kb_setImageURL:(id)url placeholder:(UIImage *)placeholder {
|
||||||
|
[self kb_setImageURL:url placeholder:placeholder options:KBWebImageDefaultOptions()];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)kb_setImageURL:(id)url placeholder:(UIImage *)placeholder options:(NSUInteger)options {
|
||||||
|
NSURL *u = _KBURL(url);
|
||||||
|
// 默认渐隐动画
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
[self sd_setImageWithURL:u
|
||||||
|
placeholderImage:placeholder
|
||||||
|
options:options
|
||||||
|
progress:nil
|
||||||
|
completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
|
||||||
|
if (!error && image && cacheType == SDImageCacheTypeNone) {
|
||||||
|
// 网络新图,做一次淡入动画
|
||||||
|
weakSelf.alpha = 0.0;
|
||||||
|
[UIView animateWithDuration:0.25 animations:^{ weakSelf.alpha = 1.0; }];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)kb_setImageURL:(id)url
|
||||||
|
placeholder:(UIImage *)placeholder
|
||||||
|
thumbnailToFit:(BOOL)thumbnailToFit
|
||||||
|
targetSize:(CGSize)targetPixelSize {
|
||||||
|
NSURL *u = _KBURL(url);
|
||||||
|
SDWebImageOptions options = KBWebImageDefaultOptions();
|
||||||
|
NSMutableDictionary<SDWebImageContextOption, id> *context = [NSMutableDictionary dictionary];
|
||||||
|
|
||||||
|
if (thumbnailToFit) {
|
||||||
|
CGFloat scale = UIScreen.mainScreen.scale;
|
||||||
|
CGSize size = self.bounds.size;
|
||||||
|
if (CGSizeEqualToSize(size, CGSizeZero) && !CGSizeEqualToSize(targetPixelSize, CGSizeZero)) {
|
||||||
|
size = CGSizeMake(targetPixelSize.width/scale, targetPixelSize.height/scale);
|
||||||
|
}
|
||||||
|
if (!CGSizeEqualToSize(size, CGSizeZero)) {
|
||||||
|
CGSize pixelSize = CGSizeMake(size.width * scale, size.height * scale);
|
||||||
|
context[SDWebImageContextImageThumbnailPixelSize] = @(pixelSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
[self sd_setImageWithURL:u
|
||||||
|
placeholderImage:placeholder
|
||||||
|
options:options
|
||||||
|
context:context
|
||||||
|
progress:nil
|
||||||
|
completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
|
||||||
|
if (!error && image && cacheType == SDImageCacheTypeNone) {
|
||||||
|
weakSelf.alpha = 0.0;
|
||||||
|
[UIView animateWithDuration:0.25 animations:^{ weakSelf.alpha = 1.0; }];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)kb_setImageURL:(id)url
|
||||||
|
placeholder:(UIImage *)placeholder
|
||||||
|
cornerRadius:(CGFloat)radius
|
||||||
|
corners:(UIRectCorner)corners
|
||||||
|
borderWidth:(CGFloat)borderWidth
|
||||||
|
borderColor:(UIColor *)borderColor {
|
||||||
|
NSURL *u = _KBURL(url);
|
||||||
|
SDWebImageOptions options = KBWebImageDefaultOptions();
|
||||||
|
|
||||||
|
// 组合圆角 + 缩略(按视图大小)
|
||||||
|
CGFloat scale = UIScreen.mainScreen.scale;
|
||||||
|
CGSize size = self.bounds.size;
|
||||||
|
NSMutableArray<id<SDImageTransformer>> *trans = [NSMutableArray array];
|
||||||
|
if (!CGSizeEqualToSize(size, CGSizeZero)) {
|
||||||
|
// 先按像素缩到视图大小,避免在解码后再裁切浪费内存
|
||||||
|
CGSize pixel = CGSizeMake(size.width * scale, size.height * scale);
|
||||||
|
[trans addObject:[SDImageResizingTransformer transformerWithSize:pixel scaleMode:SDImageScaleModeAspectFill]];
|
||||||
|
}
|
||||||
|
[trans addObject:[SDImageRoundCornerTransformer transformerWithRadius:radius
|
||||||
|
corners:(SDRectCorner)corners
|
||||||
|
borderWidth:borderWidth
|
||||||
|
borderColor:borderColor]];
|
||||||
|
SDImagePipelineTransformer *pipeline = [SDImagePipelineTransformer transformerWithTransformers:trans];
|
||||||
|
|
||||||
|
NSDictionary *context = @{ SDWebImageContextImageTransformer : pipeline };
|
||||||
|
|
||||||
|
__weak typeof(self) weakSelf = self;
|
||||||
|
[self sd_setImageWithURL:u
|
||||||
|
placeholderImage:placeholder
|
||||||
|
options:options
|
||||||
|
context:context
|
||||||
|
progress:nil
|
||||||
|
completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
|
||||||
|
if (!error && image && cacheType == SDImageCacheTypeNone) {
|
||||||
|
weakSelf.alpha = 0.0;
|
||||||
|
[UIView animateWithDuration:0.25 animations:^{ weakSelf.alpha = 1.0; }];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)kb_setAvatarURL:(id)url placeholder:(UIImage *)placeholder {
|
||||||
|
// 圆形:以视图最短边的一半为半径
|
||||||
|
CGSize sz = self.bounds.size;
|
||||||
|
CGFloat r = MIN(sz.width, sz.height) * 0.5;
|
||||||
|
if (r <= 0) {
|
||||||
|
// 若尚未布局,使用占位图尺寸估算
|
||||||
|
r = MIN(placeholder.size.width, placeholder.size.height) * 0.5;
|
||||||
|
}
|
||||||
|
[self kb_setImageURL:url
|
||||||
|
placeholder:placeholder
|
||||||
|
cornerRadius:r
|
||||||
|
corners:UIRectCornerAllCorners
|
||||||
|
borderWidth:0
|
||||||
|
borderColor:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)kb_cancelImageLoad {
|
||||||
|
[self sd_cancelCurrentImageLoad];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -26,6 +26,10 @@
|
|||||||
label.center = self.view.center;
|
label.center = self.view.center;
|
||||||
label.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
|
label.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin;
|
||||||
[self.view addSubview:label];
|
[self.view addSubview:label];
|
||||||
|
|
||||||
|
[[KBNetworkManager shared] GET:@"https://m1.apifoxmock.com/m1/5438099-5113192-default/app/config" parameters:nil headers:nil completion:^(id _Nullable jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||||
|
NSLog(@"====");
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
|
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
|
||||||
|
|||||||
57
keyBoard/Class/Network/KBNetworkManager.h
Normal file
57
keyBoard/Class/Network/KBNetworkManager.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// KBNetworkManager.h
|
||||||
|
// CustomKeyboard
|
||||||
|
//
|
||||||
|
// 轻量网络层封装(扩展安全)。支持 GET/POST(JSON)。
|
||||||
|
// 注意:键盘扩展需要"允许完全访问"后才可联网,
|
||||||
|
// 建议由宿主控制器在确认后调用 `setEnabled:YES` 再发起请求。
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
extern NSErrorDomain const KBNetworkErrorDomain;
|
||||||
|
typedef NS_ERROR_ENUM(KBNetworkErrorDomain, KBNetworkError) {
|
||||||
|
KBNetworkErrorDisabled = 1, // 未启用网络(例如未开启完全访问)
|
||||||
|
KBNetworkErrorInvalidURL = 2,
|
||||||
|
KBNetworkErrorInvalidResponse = 3,
|
||||||
|
KBNetworkErrorDecodeFailed = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// 简单的 JSON 回调:json 为 NSDictionary/NSArray 或者在非 JSON 情况下返回 NSData
|
||||||
|
typedef void(^KBNetworkCompletion)(id _Nullable jsonOrData, NSURLResponse * _Nullable response, NSError * _Nullable error);
|
||||||
|
|
||||||
|
@interface KBNetworkManager : NSObject
|
||||||
|
|
||||||
|
/// 单例
|
||||||
|
+ (instancetype)shared;
|
||||||
|
|
||||||
|
/// 是否允许网络(默认为 NO,宿主在合适时机置 YES)
|
||||||
|
@property (atomic, assign, getter=isEnabled) BOOL enabled;
|
||||||
|
|
||||||
|
/// 可选的基础域名,例如 https://api.example.com
|
||||||
|
@property (nonatomic, strong, nullable) NSURL *baseURL;
|
||||||
|
|
||||||
|
/// 全局默认请求头(每次请求会与局部 headers 合并,局部优先)
|
||||||
|
@property (nonatomic, copy) NSDictionary<NSString *, NSString *> *defaultHeaders;
|
||||||
|
|
||||||
|
/// 超时时间(默认 10s)
|
||||||
|
@property (nonatomic, assign) NSTimeInterval timeout;
|
||||||
|
|
||||||
|
/// GET 请求,parameters 会拼到 URL 上
|
||||||
|
- (nullable NSURLSessionDataTask *)GET:(NSString *)path
|
||||||
|
parameters:(nullable NSDictionary *)parameters
|
||||||
|
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
||||||
|
completion:(KBNetworkCompletion)completion;
|
||||||
|
|
||||||
|
/// POST JSON 请求,jsonBody 会以 application/json 发送
|
||||||
|
- (nullable NSURLSessionDataTask *)POST:(NSString *)path
|
||||||
|
jsonBody:(nullable id)jsonBody
|
||||||
|
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
||||||
|
completion:(KBNetworkCompletion)completion;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
164
keyBoard/Class/Network/KBNetworkManager.m
Normal file
164
keyBoard/Class/Network/KBNetworkManager.m
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
//
|
||||||
|
// KBNetworkManager.m
|
||||||
|
// CustomKeyboard
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "KBNetworkManager.h"
|
||||||
|
#import "AFNetworking.h"
|
||||||
|
|
||||||
|
NSErrorDomain const KBNetworkErrorDomain = @"com.company.keyboard.network";
|
||||||
|
|
||||||
|
@interface KBNetworkManager ()
|
||||||
|
@property (nonatomic, strong) AFHTTPSessionManager *manager; // AFN 管理器(ephemeral 配置)
|
||||||
|
// 私有错误派发
|
||||||
|
- (void)fail:(KBNetworkError)code completion:(KBNetworkCompletion)completion;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation KBNetworkManager
|
||||||
|
|
||||||
|
+ (instancetype)shared {
|
||||||
|
static KBNetworkManager *m; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ m = [KBNetworkManager new]; });
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
if (self = [super init]) {
|
||||||
|
_enabled = NO; // 键盘扩展默认无网络能力,需外部显式开启
|
||||||
|
_timeout = 10.0;
|
||||||
|
_defaultHeaders = @{ @"Accept": @"application/json" };
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Public
|
||||||
|
|
||||||
|
- (NSURLSessionDataTask *)GET:(NSString *)path
|
||||||
|
parameters:(NSDictionary *)parameters
|
||||||
|
headers:(NSDictionary<NSString *,NSString *> *)headers
|
||||||
|
completion:(KBNetworkCompletion)completion {
|
||||||
|
if (![self ensureEnabled:completion]) return nil;
|
||||||
|
NSString *urlString = [self buildURLStringWithPath:path];
|
||||||
|
if (!urlString) { [self fail:KBNetworkErrorInvalidURL completion:completion]; return nil; }
|
||||||
|
// 使用 AFHTTPRequestSerializer 生成带参数与头的请求
|
||||||
|
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
|
||||||
|
serializer.timeoutInterval = self.timeout;
|
||||||
|
NSMutableURLRequest *req = [serializer requestWithMethod:@"GET"
|
||||||
|
URLString:urlString
|
||||||
|
parameters:parameters
|
||||||
|
error:NULL];
|
||||||
|
[self applyHeaders:headers toMutableRequest:req contentType:nil];
|
||||||
|
return [self startAFTaskWithRequest:req completion:completion];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSURLSessionDataTask *)POST:(NSString *)path
|
||||||
|
jsonBody:(id)jsonBody
|
||||||
|
headers:(NSDictionary<NSString *,NSString *> *)headers
|
||||||
|
completion:(KBNetworkCompletion)completion {
|
||||||
|
if (![self ensureEnabled:completion]) return nil;
|
||||||
|
NSString *urlString = [self buildURLStringWithPath:path];
|
||||||
|
if (!urlString) { [self fail:KBNetworkErrorInvalidURL completion:completion]; return nil; }
|
||||||
|
// 用 JSON 序列化器生成 JSON Body 的请求
|
||||||
|
AFJSONRequestSerializer *serializer = [AFJSONRequestSerializer serializer];
|
||||||
|
serializer.timeoutInterval = self.timeout;
|
||||||
|
NSError *error = nil;
|
||||||
|
NSMutableURLRequest *req = [serializer requestWithMethod:@"POST"
|
||||||
|
URLString:urlString
|
||||||
|
parameters:jsonBody
|
||||||
|
error:&error];
|
||||||
|
if (error) { if (completion) completion(nil, nil, error); return nil; }
|
||||||
|
[self applyHeaders:headers toMutableRequest:req contentType:nil];
|
||||||
|
return [self startAFTaskWithRequest:req completion:completion];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Core
|
||||||
|
|
||||||
|
- (BOOL)ensureEnabled:(KBNetworkCompletion)completion {
|
||||||
|
if (!self.isEnabled) {
|
||||||
|
NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorDisabled userInfo:@{NSLocalizedDescriptionKey: @"网络未启用(可能未开启完全访问)"}];
|
||||||
|
if (completion) completion(nil, nil, e);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)buildURLStringWithPath:(NSString *)path {
|
||||||
|
if (path.length == 0) return nil;
|
||||||
|
if ([path hasPrefix:@"http://"] || [path hasPrefix:@"https://"]) {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
if (self.baseURL) {
|
||||||
|
return [NSURL URLWithString:path relativeToURL:self.baseURL].absoluteURL.absoluteString;
|
||||||
|
}
|
||||||
|
return path; // 当无 baseURL 且 path 不是完整 URL 时,让 AFN 处理(可能失败)
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applyHeaders:(NSDictionary<NSString *,NSString *> *)headers toMutableRequest:(NSMutableURLRequest *)req contentType:(NSString *)contentType {
|
||||||
|
// 合并默认头与局部头,局部覆盖
|
||||||
|
NSMutableDictionary *all = [self.defaultHeaders mutableCopy] ?: [NSMutableDictionary new];
|
||||||
|
if (contentType) all[@"Content-Type"] = contentType;
|
||||||
|
[headers enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { all[key] = obj; }];
|
||||||
|
[all enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { [req setValue:obj forHTTPHeaderField:key]; }];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSURLSessionDataTask *)startAFTaskWithRequest:(NSURLRequest *)req completion:(KBNetworkCompletion)completion {
|
||||||
|
// 响应先用原始数据返回,再按 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; }
|
||||||
|
NSData *data = (NSData *)responseObject;
|
||||||
|
if (![data isKindOfClass:[NSData class]]) {
|
||||||
|
if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorInvalidResponse userInfo:@{NSLocalizedDescriptionKey:@"无数据"}]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSString *ct = nil;
|
||||||
|
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||||
|
ct = ((NSHTTPURLResponse *)response).allHeaderFields[@"Content-Type"];
|
||||||
|
}
|
||||||
|
BOOL looksJSON = (ct && [ct.lowercaseString containsString:@"application/json"]);
|
||||||
|
if (looksJSON) {
|
||||||
|
NSError *jsonErr = nil;
|
||||||
|
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonErr];
|
||||||
|
if (jsonErr) { if (completion) completion(nil, response, [NSError errorWithDomain:KBNetworkErrorDomain code:KBNetworkErrorDecodeFailed userInfo:@{NSLocalizedDescriptionKey:@"JSON解析失败"}]); return; }
|
||||||
|
if (completion) completion(json, response, nil);
|
||||||
|
} else {
|
||||||
|
if (completion) completion(data, response, nil);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
[task resume];
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - AFHTTPSessionManager
|
||||||
|
|
||||||
|
- (AFHTTPSessionManager *)manager {
|
||||||
|
if (!_manager) {
|
||||||
|
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration ephemeralSessionConfiguration];
|
||||||
|
cfg.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
|
||||||
|
cfg.timeoutIntervalForRequest = self.timeout;
|
||||||
|
cfg.timeoutIntervalForResource = MAX(self.timeout, 30.0);
|
||||||
|
if (@available(iOS 11.0, *)) { cfg.waitsForConnectivity = YES; }
|
||||||
|
_manager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:cfg];
|
||||||
|
// 默认不使用 JSON 解析器,保持原生数据,再按需解析
|
||||||
|
_manager.responseSerializer = [AFHTTPResponseSerializer serializer];
|
||||||
|
}
|
||||||
|
return _manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Private helpers
|
||||||
|
|
||||||
|
- (void)fail:(KBNetworkError)code completion:(KBNetworkCompletion)completion {
|
||||||
|
NSString *msg = @"网络错误";
|
||||||
|
switch (code) {
|
||||||
|
case KBNetworkErrorDisabled: msg = @"网络未启用(可能未开启完全访问)"; break;
|
||||||
|
case KBNetworkErrorInvalidURL: msg = @"无效的URL"; break;
|
||||||
|
case KBNetworkErrorInvalidResponse: msg = @"无效的响应"; break;
|
||||||
|
case KBNetworkErrorDecodeFailed: msg = @"解析失败"; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
NSError *e = [NSError errorWithDomain:KBNetworkErrorDomain
|
||||||
|
code:code
|
||||||
|
userInfo:@{NSLocalizedDescriptionKey: msg}];
|
||||||
|
if (completion) completion(nil, nil, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
/// 系统
|
/// 系统
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import "KBHUD.h"
|
#import "KBHUD.h"
|
||||||
|
#import "KBNetworkManager.h"
|
||||||
|
|
||||||
|
|
||||||
/// 项目
|
/// 项目
|
||||||
#import "BaseNavigationController.h"
|
#import "BaseNavigationController.h"
|
||||||
|
|||||||
Reference in New Issue
Block a user