第三方框架
项目中使用到以下第三方框架
AFNetworking
SDWebImage
SVProgressHUD
SnapKit
Pod 安装
- git 备份
- 打开终端
-
$ cd
进入项目目录 - 输入以下终端命令建立或编辑
Podfile
$ touch Podfile
- 将 Podfile 拖入 Xcode 输入以下内容
use_frameworks!
platform :ios, '8.0'
pod 'AFNetworking'
pod 'SDWebImage'
pod 'SVProgressHUD'
pod 'SnapKit'
- 输入以下命令安装第三方框架
$ pod install
// 如果太慢可以尝试:
// $ pod install --verbose --no-repo-update
- 如果第三方框架不能正常工作或者升级,可以输入以下命令更新
$ pod update
在 Swift 项目中,cocoapod 仅支持以 Framework 方式添加框架,因此需要在 Podfile 中添加
use_frameworks!
AFNetworking
ATS 设置
<key>NSAppTransportSecurity</key>
<dict>
<!--Include to allow all connections (DANGER)-->
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
封装网络框架的必要性
- 在应用程序开发中,一定要封装隔离网络框架
- 示意图如下:
OC 封装网络工具
- 新建网络工具类
NetworkTools
- 实现单例
+ (instancetype)sharedTools {
static NetworkTools *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[NetworkTools alloc] initWithBaseURL:nil];
instance.responseSerializer.acceptableContentTypes = [instance.responseSerializer.acceptableContentTypes setByAddingObject:@"text/html"];
});
return instance;
}
- 建立网络请求方法
- (void)request:(NSString *)URLString parameters:(id)parameters finished:(void (^)(id result, NSError *error))finished {
NSAssert(finished != nil, @"必须输入完成回调");
[self GET:URLString parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
finished(responseObject, nil);
} failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
finished(nil, error);
}];
}
- 测试网络请求
[[NetworkTools sharedTools] request:@"http://www.weather.com.cn/data/sk/101010100.html" parameters:nil finished:^(id result, NSError *error) {
NSLog(@"%@ %@", result, error);
}];
- 定义 HTTP 请求枚举类型
/// 网络请求枚举类型
typedef enum : NSUInteger {
GET,
POST,
} HMRequestMethod;
- 从
AFHTTPSessionManager.m
中复制dataTaskWithHTTPMethod
函数定义
@protocol NetworkToolsProxy <NSObject>
/// AFN 内部网络请求方法
///
/// @param method 请求方法
/// @param URLString URLString
/// @param parameters 参数字典
/// @param success 成功回调
/// @param failure 失败回调
///
/// @return NSURLSessionDataTask,需要 resume
@optional
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(NSURLSessionDataTask *, id))success
failure:(void (^)(NSURLSessionDataTask *, NSError *))failure;
@end
- 修改
request
方法
- (void)request:(HMRequestMethod)method URLString:(NSString *)URLString parameters:(id)parameters finished:(void (^)(id result, NSError *error))finished {
NSAssert(finished != nil, @"必须输入完成回调!");
NSString *methodName = (method == GET) ? @"GET" : @"POST";
[[self dataTaskWithHTTPMethod:methodName URLString:URLString parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
finished(responseObject, nil);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"%@", error);
finished(nil, error);
}] resume];
}
- 测试 GET 请求
[[NetworkTools sharedTools] request:GET URLString:@"http://www.weather.com.cn/data/sk/101010100.html" parameters:nil finished:^(id result, NSError *error) {
NSLog(@"%@ %@", result, error);
}];
- 测试 POST 请求
[[NetworkTools sharedTools] request:POST URLString:@"http://httpbin.org/post" parameters:@{@"name": @"zhangsan", @"age": @18} finished:^(id result, NSError *error) {
NSLog(@"%@ %@", result, error);
}];
Swift 封装网络工具
- 网络请求方法枚举
/// 请求方法
enum HMRequestMethod: String {
case GET = "GET"
case POST = "POST"
}
- 单例 & 响应格式设置方法
/// 网络工具类
class NetworkTools: AFHTTPSessionManager {
/// 网络工具单例
static let sharedTools: NetworkTools = {
let tools = NetworkTools(baseURL: nil)
tools.responseSerializer.acceptableContentTypes?.insert("text/html")
return tools
}()
}
- AFN 内部方法封装
// MARK: - 封装 AFN 内部方法
extension NetworkTools {
/// 请求回调
typealias RequestCallBack = (result: AnyObject?, error: NSError?) -> ()
/// 网络请求方法
///
/// - parameter method: 请求方法 GET / POST
/// - parameter URLString: URLString
/// - parameter parameters: 参数字典
/// - parameter finished: 完成回调
func request(method: HMRequestMethod, URLString: String, parameters: [String: AnyObject]?, finished:RequestCallBack) {
// 成功回调
let success = { (task: NSURLSessionDataTask, result: AnyObject) -> Void in
finished(result: result, error: nil)
}
// 失败回调
let failure = { (task: NSURLSessionDataTask, error: NSError) -> Void in
print(error)
finished(result: nil, error: error)
}
if method == HMRequestMethod.GET {
GET(URLString, parameters: parameters, success: success, failure: failure)
} else {
POST(URLString, parameters: parameters, success: success, failure: failure)
}
}
}
小结
- 使用
typealias
可以统一和简化闭包的定义和传递 - 使用
baseURL
能够简化网络访问方法中 URL 的传递 - AFN 访问方法最常见的错误
-
status code == 200
,但是提示unacceptable content-type
,表示网络访问正常,但是无法对返回数据做反序列化 - 解决办法:增加 反序列化数据 格式
-
- 另外一个常见错误
-
status code == 405
,不支持的网络请求方法,检查 GET / POST 是否写错
-
SDWebImage & SVProgressHUD
SVProgressHUD
-
SVProgressHUD
是使用 OC 开发的指示器 - 使用非常广泛
框架地址
https://github.com/TransitApp/SVProgressHUD
与 MBProgressHUD
对比
-
SVProgressHUD
- 只支持
ARC
- 支持较新的苹果 API
- 提供有素材包
- 使用更简单
- 只支持
-
MBProgressHUD
- 支持
ARC
&MRC
- 没有素材包,程序员需要针对框架进行一定的定制才能使用
- 支持
使用
import SVProgressHUD
SVProgressHUD.showInfoWithStatus("正在玩命加载中...", maskType: SVProgressHUDMaskType.Gradient)
SDWebImage
import SDWebImage
let url = NSURL(string: "http://img0.bdstatic.com/img/image/6446027056db8afa73b23eaf953dadde1410240902.jpg")!
SDWebImageManager.sharedManager().downloadImageWithURL(url, options: SDWebImageOptions.allZeros, progress: nil) { (image, _, _, _, _) in
let data = UIImagePNGRepresentation(image)
data.writeToFile("/Users/apple/Desktop/123.jpg", atomically: true)
}
SnapKit
SnapKit
是 Masonry
框架的团队针对 Swift 全新开发的一套自动布局框架
官方网站:http://snapkit.io
github网站:https://github.com/SnapKit/SnapKit
SnapKit语法示意图如下:
代码演练
使用
SnapKit
替换访客视图中的自动布局代码导入框架
import SnapKit
- 设置布局
// 2.1 图标
iconView.snp_makeConstraints { (make) -> Void in
make.center.equalTo(self)
}
// 2.2 圆圈
circleView.snp_makeConstraints { (make) -> Void in
make.center.equalTo(iconView)
}
// 2.3 消息
messageLabel.snp_makeConstraints { (make) -> Void in
make.width.equalTo(224)
make.top.equalTo(circleView.snp_bottom).offset(16)
make.centerX.equalTo(circleView)
}
// 2.4 注册按钮
registerButton.snp_makeConstraints { (make) -> Void in
make.leading.equalTo(messageLabel)
make.top.equalTo(messageLabel.snp_bottom).offset(16)
make.size.equalTo(CGSizeMake(100, 35))
}
// 2.5 登录按钮
loginButton.snp_makeConstraints { (make) -> Void in
make.trailing.equalTo(messageLabel)
make.centerY.equalTo(registerButton)
make.size.equalTo(CGSizeMake(100, 35))
}
// 2.6 阴影按钮
maskIconView.snp_makeConstraints { (make) -> Void in
make.top.equalTo(self)
make.bottom.equalTo(registerButton)
make.width.equalTo(self)
}