问题
cocoapods 安装Alamofire出现的问题,执行pad install之后没有生成对应的xxx.xcworkspace的文件(Podfile文件格式没有错误)
网上查询可能是ruby版本问题(其实应该是cocoapods自身问题,升级到1.1.1之后),开始升级ruby(用brew安装更加方便)
1.安装rvm
curl -L get.rvm.io | bash -s stable
2.测试是否安装正常
rvm -v
出现版本号代表安装正常
-
查看ruby的所有的版本号
-
rvm list konwn
-
选择一个版本安装,我这里是2.4.0
-
升级
-
rvm install 2.4.0
-
出现错误如下
-
Searching for binary rubies, this might take some time. No binary rubies available for: osx/10.12/x86_64/ruby-2.2.4. Continuing with compilation. Please read ‘rvm help mount’ to get more information on binary rubies. Checking requirements for osx. Installing requirements for osx. Updating system – please wait Error running requirements_osx_brew_update_system ruby-2.2.4′, showing last 15 lines of /Users/xielibin/.rvm/log/1487058803_ruby-2.2.4/update_system.log +rvm_error:2> rvm_pretty_print stderr +rvm_pretty_print:2> case auto (0|no) +rvm_pretty_print:2> case auto (1|auto) +rvm_pretty_print:7> case xterm-new (dumb|unknown) +rvm_pretty_print:10> case stderr (stdout) +rvm_pretty_print:10> case stderr (stderr) +rvm_pretty_print:12> [[ -t 2 ]] +rvm_pretty_print:12> return 1 +rvm_error:4> printf %b Failed to update Homebrew, follow instructions here: https://github.com/Homebrew/homebrew/wiki/Common-Issues and make surebrew updateworks before continuing.\n Failed to update Homebrew, follow instructions here: https://github.com/Homebrew/homebrew/wiki/Common-Issues and make surebrew updateworks before continuing. +requirements_osx_brew_update_system:25> return 1 Requirements installation failed with status: 1.
万能的stackoverflow上看了一下,试了如下的命令
Whoops, the Homebrew installer has moved! Please instead run:ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)”
还是出现错误:
Error running ‘requirements_osx_brew_libs_install automake’,
showing last 15 lines of /Users/xielibin/.rvm/log/1487059577_ruby-2.4.0/package_install_automake.log
+rvm_pretty_print:10> case stdout (stdout)
+rvm_pretty_print:11> [[ -t 1 ]]
+rvm_pretty_print:11> return 1
+rvm_warn:4> printf %b ‘There were package installation errors, make sure to read the log.
Try brew tap –repair and make sure brew doctor looks reasonable.
Check Homebrew requirements https://github.com/Homebrew/homebrew/wiki/Installation\n‘
There were package installation errors, make sure to read the log.
Try brew tap –repair and make sure brew doctor looks reasonable.
Check Homebrew requirements https://github.com/Homebrew/homebrew/wiki/Installation
+requirements_osx_brew_libs_install:8> case 10.12 (10.6)
+requirements_osx_brew_libs_install:15> return 1
Requirements installation failed with status: 1.
brew的配置问题
brew doctor检查
链接
brew link
完成之后
brew install ruby
升级到最新版
备注:完成ruby升级,如果问题还存在(我就存在),那就是cocoapods升级的bug,重新升级安装 sudo gem install cocoapods,重新执行pod install 成功!
解读的一些内容
前言:Alamofire与AFNetWorking是同一个大神写的
0.一些学习的tips
1.将系统的关键字用作变量:`default`, `self`等;
2.一个函数返回结果没有使用系统会有警告,利用@discardableResult可以消除警告;
3.swift2.0的关键字defer(我们用的也比较少):
语法 defer{ code }
使用:每一个defer代码块生成之后被放进一个栈中(先进后出),所以这里的代码是自下而上执行的。看一行代码:
func lookforSomething(name:String){ //这里是作用域1 整个函数作用域 print(“1-1”) if name == “”{ //这里是作用域2 if的作用域 print(“2-1”) defer{ print(“2-2”) } print(“2-3”) } print(“1-2”) defer{ print(“1-3”) } print(“1-4”) if name == “hello”{ //作用域3 print(“3-1”) defer{ print(“3-2”) } print(“3-3”) defer{ print(“3-4”) } } }
4.避免使用字符串:字符串很容易写错,写错也没有提示,用的地方多了问题就会出现,保不齐什么地方就写错,引起bug,用起来也不爽,看一下Alamofire的使用:
extension Notification.Name { // Used as a namespace for all `URLSessionTask` related notifications. public struct Task { // Posted when a `URLSessionTask` is resumed. The notification `object` contains the resumed `URLSessionTask`. public static let DidResume = Notification.Name(rawValue: “org.alamofire.notification.name.task.didResume”) //Posted when a `URLSessionTask` is suspended. The notification `object` contains the suspended `URLSessionTask`. public static let DidSuspend = Notification.Name(rawValue: “org.alamofire.notification.name.task.didSuspend”) //Posted when a `URLSessionTask` is cancelled. The notification `object` contains the cancelled `URLSessionTask`. public static let DidCancel = Notification.Name(rawValue: “org.alamofire.notification.name.task.didCancel”) // Posted when a `URLSessionTask` is completed. The notification `object` contains the completed `URLSessionTask`. public static let DidComplete = Notification.Name(rawValue: “org.alamofire.notification.name.task.didComplete”) } } extension Notification { // Used as a namespace for all `Notification` user info dictionary keys. public struct Key { // User info dictionary key representing the `URLSessionTask` associated with the notification. public static let Task = “org.alamofire.notification.key.task” } }
使用起来就是 Notification.Name.DidResume.rawValue,这样地方多了都不会错。当然定义常量也是可以的,但毕竟swift有这么好的方法,干嘛走老路呢。文件代码很少,用起来却比较的强大。
执行的作用域:defer里面的代码总是在作用域结束之后自下而上调用,可以跑一下自己试试。
场景:可以处理一些错误的逻辑。比如一个函数有1,2,3,4操作,1操作失败需要1.1的处理,2失败需要2.1的处理以此类推,当然defer是自下而上的执行,顺序别弄错(失败的操作依次是4.1-3.1-2.1-1.1),这样写起来相对比自己再去定义方法写一些逻辑要好一点(纯个人理解,我也没用过,理解不是很深)。
1. 整体框架结构
Alamofire.swift: 主要的外部调用的类,发起请求的类,用户可以方便的使用这个类区调用Alamofire的主要功能。
与3.0之前版本的一些区别:3.0的版本一个是转化NSURL(NSURLRequest)为String,即请求的地址的转化。细说就是, 定义URLStringConvertible接口,把系统 String,NSURL,NSURLComponents,NSURLReques转化为String地址,另一个转化NSURLRequest为NSMutableURLRequest;4.0以后的版本是为了swift3做的改变,将地址转化成URL类型,这里增加了错误类型,转化失败会抛出异常,定义URLConvertible接口(与3.0相反),URLRequestConvertible转化成URLRequest,这样做可以做到比较的统一,swift的新思想:面向协议。
SessionManager.swift(3.0版本的Manager.swift): 这是一个单列,主要负责request,封装系统的URLSession等网络请求的类,上述文件中主要调用的就是这个类的方法。
AFError.swift: 封装了各种错误的信息。
Notifications.swift:扩展系统的通知名字,避免使用字符串写错,定义了didResume,didSuspend,didCancel,didComplete等通知名。
ParameterEncoding.swift:定义了参数的编码方式,以ParameterEncoding为接口定义了URLEncoding,JSONEncoding,PropertyListEncoding三种方式,其实就是包装request。
Request.swift: 一共有四个类型:DataRequest, DownloadRequest, UploadRequest, StreamRequest,init会根据不同的类型生成不同的TaskDelegate来处理回调。
Response.swift:对应的也有DefaultDataResponse, DataResponse, DefaultDownloadResponse, DownloadResponse四个类型,四个相互独立没有继承关系,用来解析系统的。
Result.swift:主要就是用于返回接口的解析包装,生成结果对象方便使用(成功及失败的模型)。
SessionDelegate.swift:处理session代理的回调,实际真正处理的是TaskDelegate,封装的较深,可以看做是TaskDelegate的管理者,利用下标去处理request。
TaskDelegate.swift:真正处理session代理的回调。
备注:以上是核心的类
MultipartFormData.swift:用于上传数据(multipart/form-data)的构造类。
NetworkReachabilityManager.swift:用于检测网络的类,封装了SCNetworkReachability。
ResponseSerialization.swift: 用于解析response的工具,可以解析成三种Data ,String,JSON类型;扩展了request,DataRequest,DownloadRequest三个类,基本思想是根据不同的request生成不同的ResponseSerializer(都有遵循的协议),然后按照三种不同的类型去解析。
ServerTrustPolicy.swift:安全策略,使用证书等保证请求的安全。
Timeline.swift:用于开发者调试的类,可以打印一个请求的开始,结束,总时间等。
Validation.swift:请求的验证类,一些错误码 MIMEType错误等的处理。
备注:以上可以看作是工具(辅助)的类
DispatchQueue+Alamofire.swift:简单封装GCD queue的方法。
备注:GCD queue的分类
2.内容解读
2.1 构造一个框架的一些感想
首先,划分不同的功能,这个框架需要实现的主要功能和辅助功能的划分;其次,根据不同的功能封装不同的类区处理逻辑,数据,视图;最后,用一个全局的单列或者其他的管理者去方便的使用。宗旨是要用户方便的使用你的框架。
大致看了Alamofire这个框架,代码不算多,但是分的比较细,功能比较全,使用起来也是很方便。我们之前写的代码时间久了,可能会导致某一个类比较冗陈,可以学习这里的一些封装方法适当的抽代码,给一个类瘦身。
这个框架用来学习swift的新特性也是不错的,里面的类很多面向协议,这是swift的一大特色。协议比较容易扩展,相对方便维护。泛型和协议,用好这两个特性,可以省去比较多的时间,写出来的代码也比较优雅(还有一个是函数式编程)。
总的来说,写一个框架需要的全局的概念,确定全局的才能到具体,一步步才能构建一个强大的框架,还有就是任何强大的框架也好,项目也好,都是由简到繁,先写出简易功能,然后一步步扩展(预留好便于扩展的接口)。
2.2URLComponents
对于URL这个类使用算是比较的熟悉了,URLComponents相对来说比较陌生。这个其实跟Date与DateComponents相同,可以获取到URL中每一部分的值,大概是这个样子;
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/ \________/\_________/ \__/
| | | | |
scheme authority path query fragment
percent-encoded:加上这个的属性都是经过百分号编码的(针对特殊的字符)。
Url编码通常也被称为百分号编码(Url Encoding,also known as percent-encoding),是因为它的编码方式非常简单,使用%百分号加上两位的字符——0123456789ABCDEF——代表一个字节的 十六进制形式。Url编码默认使用的字符集是US-ASCII。例如a在US-ASCII码中对应的字节是0x61,那么Url编码之后得到的就 是%61,我们在地址栏上输入http://g.cn/search?q=%61%62%63,实际上就等同于在google上搜索abc了。又如@符号 在ASCII字符集中对应的字节为0x40,经过Url编码之后得到的是%40。
常见字符的Url编码列表:
! |
* |
“ |
‘ |
( |
) |
; |
: |
@ |
& |
%21 |
%2A |
%22 |
%27 |
%28 |
%29 |
%3B |
%3A |
%40 |
%26 |
= |
+ |
$ |
, |
/ |
? |
% |
# |
[ |
] |
%3D |
%2B |
%24 |
%2C |
%2F |
%3F |
%25 |
%23 |
%5B |
%5D |
2.3一些封装的思想
封装要知道哪些是需要开放的,哪些需要封闭的,往往对外封闭的一些内容比较检验一个人的功底。简单的总结几点(欢迎补充):
a. 有一个总起的类可以调用开放的方法
b. 独立的东西功能一定要分开写
c. 代理和闭包同行(很多的框架都会提供两种对外传值)
2.4请求与响应(有些方法写的比较简单)
Alamofire请求与响应的历程:Alamofire.request()—-> SessionManager.default.request()—–> request.encode()(对请求进行编码,分两种:普通与错误,有三种,参考:1.整体框架结构) —–> SessionDelegate中的回调方法 ———> TaskDelegate中的回调方法 ——-> ResponseSerialization文件中的解析返回数据 ——> 完成。
大致的一个请求流程就是这样,作者把代理的回调方法都单独到SessionDelegate这个类中,底层是TaskDelegate类处理。这里分闭包调用和代理调用,我们平常的调用,
let para = [“num”: 20] let _ = request(getUrl, method: .get, parameters: para, encoding: URLEncoding.default, headers: httpHeader).responseJSON { (response) in switch response.result{ case .success(let info): self.textView.text = “\(info)” print(“———post info: \(info)”) case .failure(let error): self.textView.text = “\(error)” print(“———get error: \(error)”) } }
链式的,底层是调用TaskDelegate的代理方法,这里需要说明的一点是:在构造request的时候会持有一个TaskDelegate对象,创建这个对象的时候创建的线程会被直接挂起,
init(task: URLSessionTask?) { self.task = task self.queue = { let operationQueue = OperationQueue() operationQueue.maxConcurrentOperationCount = 1 operationQueue.isSuspended = true operationQueue.qualityOfService = .utility return operationQueue }() }
等到数据返回的时候isSuspended属性会被置为true。这个在哪里用到呢?就是在ResponseSerialization中解析的时候,当解析方法调用的时候会先在task的queue中addOperation,这个闭包中的代码会在任务完成的时候调用,这个时候的数据全部保存在task对象中,然后经过不同的处理(json,string…)返回Response出去,这样:
responseJSON { (response) in switch response.result{ case .success(let info): self.textView.text = “\(info)” print(“———post info: \(info)”) case .failure(let error): self.textView.text = “\(error)” print(“———get error: \(error)”) } }
这个闭包中就是有返回的数据(都已经封装好的)。当然用闭包那种形式也是可以的,但还是这种链式的用起来比较舒服。
最后: 分享大概就这么多吧,等下次学到更多的tips的时候在接着分享出来。
Social Menu