update pod Alamofire to 4.2.0

This commit is contained in:
imnotpopo
2017-01-11 15:52:11 +08:00
committed by qinyuhang
parent f290ecb567
commit 5280c301b0
25 changed files with 989 additions and 705 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ target 'ShadowsocksX-NG' do
use_frameworks!
# Pods for ShadowsocksX-NG
pod 'Alamofire', '~> 4.0.1'
pod 'Alamofire', '~> 4.2.0'
pod 'GCDWebServer', '~> 3.0'
target 'ShadowsocksX-NGTests' do
+5 -5
View File
@@ -1,20 +1,20 @@
PODS:
- Alamofire (4.0.1)
- Alamofire (4.2.0)
- BRLOptionParser (0.3.1)
- GCDWebServer (3.3.3):
- GCDWebServer/Core (= 3.3.3)
- GCDWebServer/Core (3.3.3)
DEPENDENCIES:
- Alamofire (~> 4.0)
- Alamofire (~> 4.2.0)
- BRLOptionParser (~> 0.3.1)
- GCDWebServer (~> 3.0)
SPEC CHECKSUMS:
Alamofire: 7682d43245de14874acd142ec137b144aa1dd335
Alamofire: aa2e09d871c9160ac53c90e83c68064a94e3dfbe
BRLOptionParser: a03256a8ff003ca1f5376c55f55f210e085a3958
GCDWebServer: 1c39a1f0763e4eb492bee021e4270fce097d3555
PODFILE CHECKSUM: fe577fe89bbdf6636ba715331bf8d97bbbee45bb
PODFILE CHECKSUM: 8e98b2fb2d6be56882a44b2ff9241a800101e1d4
COCOAPODS: 1.1.0.rc.2
COCOAPODS: 1.1.1
+22 -16
View File
@@ -55,8 +55,8 @@ In order to keep Alamofire focused specifically on core networking implementatio
## Requirements
- iOS 9.0+ / macOS 10.11+ / tvOS 9.0+ / watchOS 2.0+
- Xcode 8.0+
- iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+
- Xcode 8.1+
- Swift 3.0+
## Migration Guides
@@ -130,13 +130,13 @@ If you prefer not to use either of the aforementioned dependency managers, you c
- Open up Terminal, `cd` into your top-level project directory, and run the following command "if" your project is not initialized as a git repository:
```bash
```bash
$ git init
```
- Add Alamofire as a git [submodule](http://git-scm.com/docs/git-submodule) by running the following command:
```bash
```bash
$ git submodule add https://github.com/Alamofire/Alamofire.git
```
@@ -158,7 +158,7 @@ $ git submodule add https://github.com/Alamofire/Alamofire.git
- And that's it!
> The `Alamofire.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device.
> The `Alamofire.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device.
---
@@ -199,7 +199,7 @@ Alamofire contains five different response handlers by default including:
// Response Handler - Unserialized Response
func response(
queue: DispatchQueue?,
completionHandler: @escaping (DefaultDownloadResponse) -> Void)
completionHandler: @escaping (DefaultDataResponse) -> Void)
-> Self
// Response Data Handler - Serialized into Data
@@ -240,7 +240,7 @@ The `response` handler does NOT evaluate any of the response data. It merely for
Alamofire.request("https://httpbin.org/get").response { response in
print("Request: \(response.request)")
print("Response: \(response.response)")
print("Error: \(response.data)")
print("Error: \(response.error)")
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)")
@@ -331,7 +331,7 @@ By default, Alamofire treats any completed request to be successful, regardless
Alamofire.request("https://httpbin.org/get")
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.response { response in
.responseData { response in
switch response.result {
case .success:
print("Validation Successful")
@@ -360,7 +360,7 @@ Alamofire.request("https://httpbin.org/get").validate().responseJSON { response
Response Caching is handled on the system framework level by [`URLCache`](https://developer.apple.com/reference/foundation/urlcache). It provides a composite in-memory and on-disk cache and lets you manipulate the sizes of both the in-memory and on-disk portions.
> By default, Alamofire leverages the shared `URLCache`. In order to customize it, see the [Session Manager Configurations](#session-manager-configurations) section.
> By default, Alamofire leverages the shared `URLCache`. In order to customize it, see the [Session Manager Configurations](#session-manager) section.
### HTTP Methods
@@ -520,7 +520,7 @@ Alamofire.request("https://httpbin.org/headers", headers: headers).responseJSON
}
```
> For HTTP headers that do not change, it is recommended to set them on the `URLSessionConfiguration` so they are automatically applied to any `URLSessionTask` created by the underlying `URLSession`. For more information, see the [Session Manager Configurations](#session-manager-configurations) section.
> For HTTP headers that do not change, it is recommended to set them on the `URLSessionConfiguration` so they are automatically applied to any `URLSessionTask` created by the underlying `URLSession`. For more information, see the [Session Manager Configurations](#session-manager) section.
The default Alamofire `SessionManager` provides a default set of headers for every `Request`. These include:
@@ -528,7 +528,7 @@ The default Alamofire `SessionManager` provides a default set of headers for eve
- `Accept-Language`, which defaults to up to the top 6 preferred languages on the system, formatted like `en;q=1.0`, per [RFC 7231 §5.3.5](https://tools.ietf.org/html/rfc7231#section-5.3.5).
- `User-Agent`, which contains versioning information about the current app. For example: `iOS Example/1.0 (com.alamofire.iOS-Example; build:1; iOS 10.0.0) Alamofire/4.0.0`, per [RFC 7231 §5.5.3](https://tools.ietf.org/html/rfc7231#section-5.5.3).
If you need to customize these headers, a custom `URLSessionManagerConfiguration` should be created, the `defaultHTTPHeaders` property updated and the configuration applied to a new `SessionManager` instance.
If you need to customize these headers, a custom `URLSessionConfiguration` should be created, the `defaultHTTPHeaders` property updated and the configuration applied to a new `SessionManager` instance.
### Authentication
@@ -603,7 +603,7 @@ Alamofire.download("https://httpbin.org/image/png").responseData { response in
}
```
> The `Alamofire.download` APIs should also be used if you need to download data while your app is in the background. For more information, please see the [Session Manager Configurations](#session-manager-configurations) section.
> The `Alamofire.download` APIs should also be used if you need to download data while your app is in the background. For more information, please see the [Session Manager Configurations](#session-manager) section.
#### Download File Destination
@@ -623,7 +623,7 @@ let destination: DownloadRequest.DownloadFileDestination = { _, _ in
Alamofire.download(urlString, to: destination).response { response in
print(response)
if response.result.isSuccess, let imagePath = response.destinationURL?.path {
if response.error == nil, let imagePath = response.destinationURL?.path {
let image = UIImage(contentsOfFile: imagePath)
}
}
@@ -672,6 +672,8 @@ Alamofire.download("https://httpbin.org/image/png")
If a `DownloadRequest` is cancelled or interrupted, the underlying URL session may generate resume data for the active `DownloadRequest`. If this happens, the resume data can be re-used to restart the `DownloadRequest` where it left off. The resume data can be accessed through the download response, then reused when trying to restart the request.
> **IMPORTANT:** On the latest release of all the Apple platforms (iOS 10, macOS 10.12, tvOS 10, watchOS 3), `resumeData` is broken on background URL session configurations. There's an underlying bug in the `resumeData` generation logic where the data is written incorrectly and will always fail to resume the download. For more information about the bug and possible workarounds, please see this Stack Overflow [post](http://stackoverflow.com/a/39347461/1342462).
```swift
class ImageRequestor {
private var resumeData: Data?
@@ -711,7 +713,7 @@ class ImageRequestor {
When sending relatively small amounts of data to a server using JSON or URL encoded parameters, the `Alamofire.request` APIs are usually sufficient. If you need to send much larger amounts of data from a file URL or an `InputStream`, then the `Alamofire.upload` APIs are what you want to use.
> The `Alamofire.upload` APIs should also be used if you need to upload data while your app is in the background. For more information, please see the [Session Manager Configurations](#session-manager-configurations) section.
> The `Alamofire.upload` APIs should also be used if you need to upload data while your app is in the background. For more information, please see the [Session Manager Configurations](#session-manager) section.
#### Uploading Data
@@ -1289,8 +1291,12 @@ class OAuth2Handler: RequestAdapter, RequestRetrier {
.responseJSON { [weak self] response in
guard let strongSelf = self else { return }
if let json = response.result.value as? [String: String] {
completion(true, json["access_token"], json["refresh_token"])
if
let json = response.result.value as? [String: Any],
let accessToken = json["access_token"] as? String,
let refreshToken = json["refresh_token"] as? String
{
completion(true, accessToken, refreshToken)
} else {
completion(false, nil, nil)
}
+10
View File
@@ -132,6 +132,16 @@ public enum AFError: Error {
case responseSerializationFailed(reason: ResponseSerializationFailureReason)
}
// MARK: - Adapt Error
struct AdaptError: Error {
let error: Error
}
extension Error {
var underlyingAdaptError: Error? { return (self as? AdaptError)?.error }
}
// MARK: - Error Booleans
extension AFError {
+9
View File
@@ -222,6 +222,13 @@ public func download(
/// If `destination` is not specified, the contents will remain in the temporary location determined by the
/// underlying URL session.
///
/// On the latest release of all the Apple platforms (iOS 10, macOS 10.12, tvOS 10, watchOS 3), `resumeData` is broken
/// on background URL session configurations. There's an underlying bug in the `resumeData` generation logic where the
/// data is written incorrectly and will always fail to resume the download. For more information about the bug and
/// possible workarounds, please refer to the following Stack Overflow post:
///
/// - http://stackoverflow.com/a/39347461/1342462
///
/// - parameter resumeData: The resume data. This is an opaque data blob produced by `URLSessionDownloadTask`
/// when a task is cancelled. See `URLSession -downloadTask(withResumeData:)` for additional
/// information.
@@ -435,6 +442,7 @@ public func upload(
///
/// - returns: The created `StreamRequest`.
@discardableResult
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
public func stream(withHostName hostName: String, port: Int) -> StreamRequest {
return SessionManager.default.stream(withHostName: hostName, port: port)
}
@@ -449,6 +457,7 @@ public func stream(withHostName hostName: String, port: Int) -> StreamRequest {
///
/// - returns: The created `StreamRequest`.
@discardableResult
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
public func stream(with netService: NetService) -> StreamRequest {
return SessionManager.default.stream(with: netService)
}
+61 -1
View File
@@ -199,7 +199,39 @@ public struct URLEncoding: ParameterEncoding {
var allowedCharacterSet = CharacterSet.urlQueryAllowed
allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
var escaped = ""
//==========================================================================================================
//
// Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few
// hundred Chinese characters causes various malloc error crashes. To avoid this issue until iOS 8 is no
// longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more
// info, please refer to:
//
// - https://github.com/Alamofire/Alamofire/issues/206
//
//==========================================================================================================
if #available(iOS 8.3, *) {
escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
} else {
let batchSize = 50
var index = string.startIndex
while index != string.endIndex {
let startIndex = index
let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex
let range = startIndex..<endIndex
let substring = string.substring(with: range)
escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? substring
index = endIndex
}
}
return escaped
}
private func query(_ parameters: [String: Any]) -> String {
@@ -289,6 +321,34 @@ public struct JSONEncoding: ParameterEncoding {
return urlRequest
}
/// Creates a URL request by encoding the JSON object and setting the resulting data on the HTTP body.
///
/// - parameter urlRequest: The request to apply the JSON object to.
/// - parameter jsonObject: The JSON object to apply to the request.
///
/// - throws: An `Error` if the encoding process encounters an error.
///
/// - returns: The encoded request.
public func encode(_ urlRequest: URLRequestConvertible, withJSONObject jsonObject: Any? = nil) throws -> URLRequest {
var urlRequest = try urlRequest.asURLRequest()
guard let jsonObject = jsonObject else { return urlRequest }
do {
let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options)
if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
}
urlRequest.httpBody = data
} catch {
throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
}
return urlRequest
}
}
// MARK: -
+72 -25
View File
@@ -110,6 +110,9 @@ open class Request {
/// The response received from the server, if any.
open var response: HTTPURLResponse? { return task?.response as? HTTPURLResponse }
/// The number of times the request has been retried.
open internal(set) var retryCount: UInt = 0
let originalTask: TaskConvertible?
var startTime: CFAbsoluteTime?
@@ -351,13 +354,25 @@ open class DataRequest: Request {
let urlRequest: URLRequest
func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
let urlRequest = try self.urlRequest.adapt(using: adapter)
return queue.syncResult { session.dataTask(with: urlRequest) }
do {
let urlRequest = try self.urlRequest.adapt(using: adapter)
return queue.syncResult { session.dataTask(with: urlRequest) }
} catch {
throw AdaptError(error: error)
}
}
}
// MARK: Properties
/// The request sent or to be sent to the server.
open override var request: URLRequest? {
if let request = super.request { return request }
if let requestable = originalTask as? Requestable { return requestable.urlRequest }
return nil
}
/// The progress of fetching the response data from the server for the request.
open var progress: Progress { return dataDelegate.progress }
@@ -438,22 +453,37 @@ open class DownloadRequest: Request {
case resumeData(Data)
func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
let task: URLSessionTask
do {
let task: URLSessionTask
switch self {
case let .request(urlRequest):
let urlRequest = try urlRequest.adapt(using: adapter)
task = queue.syncResult { session.downloadTask(with: urlRequest) }
case let .resumeData(resumeData):
task = queue.syncResult { session.downloadTask(withResumeData: resumeData) }
switch self {
case let .request(urlRequest):
let urlRequest = try urlRequest.adapt(using: adapter)
task = queue.syncResult { session.downloadTask(with: urlRequest) }
case let .resumeData(resumeData):
task = queue.syncResult { session.downloadTask(withResumeData: resumeData) }
}
return task
} catch {
throw AdaptError(error: error)
}
return task
}
}
// MARK: Properties
/// The request sent or to be sent to the server.
open override var request: URLRequest? {
if let request = super.request { return request }
if let downloadable = originalTask as? Downloadable, case let .request(urlRequest) = downloadable {
return urlRequest
}
return nil
}
/// The resume data of the underlying download task if available after a failure.
open var resumeData: Data? { return downloadDelegate.resumeData }
@@ -471,7 +501,7 @@ open class DownloadRequest: Request {
NotificationCenter.default.post(
name: Notification.Name.Task.DidCancel,
object: self,
userInfo: [Notification.Key.Task: task]
userInfo: [Notification.Key.Task: task as Any]
)
}
@@ -528,26 +558,42 @@ open class UploadRequest: DataRequest {
case stream(InputStream, URLRequest)
func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
let task: URLSessionTask
do {
let task: URLSessionTask
switch self {
case let .data(data, urlRequest):
let urlRequest = try urlRequest.adapt(using: adapter)
task = queue.syncResult { session.uploadTask(with: urlRequest, from: data) }
case let .file(url, urlRequest):
let urlRequest = try urlRequest.adapt(using: adapter)
task = queue.syncResult { session.uploadTask(with: urlRequest, fromFile: url) }
case let .stream(_, urlRequest):
let urlRequest = try urlRequest.adapt(using: adapter)
task = queue.syncResult { session.uploadTask(withStreamedRequest: urlRequest) }
switch self {
case let .data(data, urlRequest):
let urlRequest = try urlRequest.adapt(using: adapter)
task = queue.syncResult { session.uploadTask(with: urlRequest, from: data) }
case let .file(url, urlRequest):
let urlRequest = try urlRequest.adapt(using: adapter)
task = queue.syncResult { session.uploadTask(with: urlRequest, fromFile: url) }
case let .stream(_, urlRequest):
let urlRequest = try urlRequest.adapt(using: adapter)
task = queue.syncResult { session.uploadTask(withStreamedRequest: urlRequest) }
}
return task
} catch {
throw AdaptError(error: error)
}
return task
}
}
// MARK: Properties
/// The request sent or to be sent to the server.
open override var request: URLRequest? {
if let request = super.request { return request }
guard let uploadable = originalTask as? Uploadable else { return nil }
switch uploadable {
case .data(_, let urlRequest), .file(_, let urlRequest), .stream(_, let urlRequest):
return urlRequest
}
}
/// The progress of uploading the payload to the server for the upload request.
open var uploadProgress: Progress { return uploadDelegate.uploadProgress }
@@ -577,6 +623,7 @@ open class UploadRequest: DataRequest {
#if !os(watchOS)
/// Specific type of `Request` that manages an underlying `URLSessionStreamTask`.
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
open class StreamRequest: Request {
enum Streamable: TaskConvertible {
case stream(hostName: String, port: Int)
+12 -3
View File
@@ -38,13 +38,17 @@ public struct DefaultDataResponse {
/// The error encountered while executing or validating the request.
public let error: Error?
/// The timeline of the complete lifecycle of the request.
public let timeline: Timeline
var _metrics: AnyObject?
init(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) {
init(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?, timeline: Timeline = Timeline()) {
self.request = request
self.response = response
self.data = data
self.error = error
self.timeline = timeline
}
}
@@ -64,7 +68,7 @@ public struct DataResponse<Value> {
/// The result of response serialization.
public let result: Result<Value>
/// The timeline of the complete lifecycle of the `Request`.
/// The timeline of the complete lifecycle of the request.
public let timeline: Timeline
var _metrics: AnyObject?
@@ -139,6 +143,9 @@ public struct DefaultDownloadResponse {
/// The error encountered while executing or validating the request.
public let error: Error?
/// The timeline of the complete lifecycle of the request.
public let timeline: Timeline
var _metrics: AnyObject?
init(
@@ -147,7 +154,8 @@ public struct DefaultDownloadResponse {
temporaryURL: URL?,
destinationURL: URL?,
resumeData: Data?,
error: Error?)
error: Error?,
timeline: Timeline = Timeline())
{
self.request = request
self.response = response
@@ -155,6 +163,7 @@ public struct DefaultDownloadResponse {
self.destinationURL = destinationURL
self.resumeData = resumeData
self.error = error
self.timeline = timeline
}
}
+22 -24
View File
@@ -84,6 +84,22 @@ public struct DownloadResponseSerializer<Value>: DownloadResponseSerializerProto
}
}
// MARK: - Timeline
extension Request {
var timeline: Timeline {
let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent()
let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime
return Timeline(
requestStartTime: self.startTime ?? CFAbsoluteTimeGetCurrent(),
initialResponseTime: initialResponseTime,
requestCompletedTime: requestCompletedTime,
serializationCompletedTime: CFAbsoluteTimeGetCurrent()
)
}
}
// MARK: - Default
extension DataRequest {
@@ -101,7 +117,8 @@ extension DataRequest {
request: self.request,
response: self.response,
data: self.delegate.data,
error: self.delegate.error
error: self.delegate.error,
timeline: self.timeline
)
dataResponse.add(self.delegate.metrics)
@@ -136,22 +153,12 @@ extension DataRequest {
self.delegate.error
)
let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent()
let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime
let timeline = Timeline(
requestStartTime: self.startTime ?? CFAbsoluteTimeGetCurrent(),
initialResponseTime: initialResponseTime,
requestCompletedTime: requestCompletedTime,
serializationCompletedTime: CFAbsoluteTimeGetCurrent()
)
var dataResponse = DataResponse<T.SerializedObject>(
request: self.request,
response: self.response,
data: self.delegate.data,
result: result,
timeline: timeline
timeline: self.timeline
)
dataResponse.add(self.delegate.metrics)
@@ -184,7 +191,8 @@ extension DownloadRequest {
temporaryURL: self.downloadDelegate.temporaryURL,
destinationURL: self.downloadDelegate.destinationURL,
resumeData: self.downloadDelegate.resumeData,
error: self.downloadDelegate.error
error: self.downloadDelegate.error,
timeline: self.timeline
)
downloadResponse.add(self.delegate.metrics)
@@ -219,16 +227,6 @@ extension DownloadRequest {
self.downloadDelegate.error
)
let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent()
let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime
let timeline = Timeline(
requestStartTime: self.startTime ?? CFAbsoluteTimeGetCurrent(),
initialResponseTime: initialResponseTime,
requestCompletedTime: requestCompletedTime,
serializationCompletedTime: CFAbsoluteTimeGetCurrent()
)
var downloadResponse = DownloadResponse<T.SerializedObject>(
request: self.request,
response: self.response,
@@ -236,7 +234,7 @@ extension DownloadRequest {
destinationURL: self.downloadDelegate.destinationURL,
resumeData: self.downloadDelegate.resumeData,
result: result,
timeline: timeline
timeline: self.timeline
)
downloadResponse.add(self.delegate.metrics)
+55 -15
View File
@@ -108,16 +108,53 @@ open class SessionDelegate: NSObject {
#if !os(watchOS)
/// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:readClosedFor:)`.
open var streamTaskReadClosed: ((URLSession, URLSessionStreamTask) -> Void)?
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
open var streamTaskReadClosed: ((URLSession, URLSessionStreamTask) -> Void)? {
get {
return _streamTaskReadClosed as? (URLSession, URLSessionStreamTask) -> Void
}
set {
_streamTaskReadClosed = newValue
}
}
/// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:writeClosedFor:)`.
open var streamTaskWriteClosed: ((URLSession, URLSessionStreamTask) -> Void)?
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
open var streamTaskWriteClosed: ((URLSession, URLSessionStreamTask) -> Void)? {
get {
return _streamTaskWriteClosed as? (URLSession, URLSessionStreamTask) -> Void
}
set {
_streamTaskWriteClosed = newValue
}
}
/// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:betterRouteDiscoveredFor:)`.
open var streamTaskBetterRouteDiscovered: ((URLSession, URLSessionStreamTask) -> Void)?
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
open var streamTaskBetterRouteDiscovered: ((URLSession, URLSessionStreamTask) -> Void)? {
get {
return _streamTaskBetterRouteDiscovered as? (URLSession, URLSessionStreamTask) -> Void
}
set {
_streamTaskBetterRouteDiscovered = newValue
}
}
/// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:streamTask:didBecome:outputStream:)`.
open var streamTaskDidBecomeInputAndOutputStreams: ((URLSession, URLSessionStreamTask, InputStream, OutputStream) -> Void)?
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
open var streamTaskDidBecomeInputAndOutputStreams: ((URLSession, URLSessionStreamTask, InputStream, OutputStream) -> Void)? {
get {
return _streamTaskDidBecomeInputStream as? (URLSession, URLSessionStreamTask, InputStream, OutputStream) -> Void
}
set {
_streamTaskDidBecomeInputStream = newValue
}
}
var _streamTaskReadClosed: Any?
var _streamTaskWriteClosed: Any?
var _streamTaskBetterRouteDiscovered: Any?
var _streamTaskDidBecomeInputStream: Any?
#endif
@@ -166,17 +203,19 @@ open class SessionDelegate: NSObject {
#endif
#if !os(watchOS)
switch selector {
case #selector(URLSessionStreamDelegate.urlSession(_:readClosedFor:)):
return streamTaskReadClosed != nil
case #selector(URLSessionStreamDelegate.urlSession(_:writeClosedFor:)):
return streamTaskWriteClosed != nil
case #selector(URLSessionStreamDelegate.urlSession(_:betterRouteDiscoveredFor:)):
return streamTaskBetterRouteDiscovered != nil
case #selector(URLSessionStreamDelegate.urlSession(_:streamTask:didBecome:outputStream:)):
return streamTaskDidBecomeInputAndOutputStreams != nil
default:
break
if #available(iOS 9.0, macOS 10.11, tvOS 9.0, *) {
switch selector {
case #selector(URLSessionStreamDelegate.urlSession(_:readClosedFor:)):
return streamTaskReadClosed != nil
case #selector(URLSessionStreamDelegate.urlSession(_:writeClosedFor:)):
return streamTaskWriteClosed != nil
case #selector(URLSessionStreamDelegate.urlSession(_:betterRouteDiscoveredFor:)):
return streamTaskBetterRouteDiscovered != nil
case #selector(URLSessionStreamDelegate.urlSession(_:streamTask:didBecome:outputStream:)):
return streamTaskDidBecomeInputAndOutputStreams != nil
default:
break
}
}
#endif
@@ -637,6 +676,7 @@ extension SessionDelegate: URLSessionDownloadDelegate {
#if !os(watchOS)
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
extension SessionDelegate: URLSessionStreamDelegate {
/// Tells the delegate that the read side of the connection has been closed.
///
+143 -32
View File
@@ -231,12 +231,14 @@ open class SessionManager {
headers: HTTPHeaders? = nil)
-> DataRequest
{
var originalRequest: URLRequest?
do {
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
let encodedURLRequest = try encoding.encode(urlRequest, with: parameters)
originalRequest = try URLRequest(url: url, method: method, headers: headers)
let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters)
return request(encodedURLRequest)
} catch {
return request(failedWith: error)
return request(originalRequest, failedWith: error)
}
}
@@ -248,9 +250,11 @@ open class SessionManager {
///
/// - returns: The created `DataRequest`.
open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
var originalRequest: URLRequest?
do {
let originalRequest = try urlRequest.asURLRequest()
let originalTask = DataRequest.Requestable(urlRequest: originalRequest)
originalRequest = try urlRequest.asURLRequest()
let originalTask = DataRequest.Requestable(urlRequest: originalRequest!)
let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
let request = DataRequest(session: session, requestTask: .data(originalTask, task))
@@ -261,15 +265,29 @@ open class SessionManager {
return request
} catch {
return request(failedWith: error)
return request(originalRequest, failedWith: error)
}
}
// MARK: Private - Request Implementation
private func request(failedWith error: Error) -> DataRequest {
let request = DataRequest(session: session, requestTask: .data(nil, nil), error: error)
if startRequestsImmediately { request.resume() }
private func request(_ urlRequest: URLRequest?, failedWith error: Error) -> DataRequest {
var requestTask: Request.RequestTask = .data(nil, nil)
if let urlRequest = urlRequest {
let originalTask = DataRequest.Requestable(urlRequest: urlRequest)
requestTask = .data(originalTask, nil)
}
let underlyingError = error.underlyingAdaptError ?? error
let request = DataRequest(session: session, requestTask: requestTask, error: underlyingError)
if let retrier = retrier, error is AdaptError {
allowRetrier(retrier, toRetry: request, with: underlyingError)
} else {
if startRequestsImmediately { request.resume() }
}
return request
}
@@ -308,7 +326,7 @@ open class SessionManager {
let encodedURLRequest = try encoding.encode(urlRequest, with: parameters)
return download(encodedURLRequest, to: destination)
} catch {
return download(failedWith: error)
return download(nil, to: destination, failedWith: error)
}
}
@@ -334,7 +352,7 @@ open class SessionManager {
let urlRequest = try urlRequest.asURLRequest()
return download(.request(urlRequest), to: destination)
} catch {
return download(failedWith: error)
return download(nil, to: destination, failedWith: error)
}
}
@@ -348,6 +366,13 @@ open class SessionManager {
///
/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
///
/// On the latest release of all the Apple platforms (iOS 10, macOS 10.12, tvOS 10, watchOS 3), `resumeData` is broken
/// on background URL session configurations. There's an underlying bug in the `resumeData` generation logic where the
/// data is written incorrectly and will always fail to resume the download. For more information about the bug and
/// possible workarounds, please refer to the following Stack Overflow post:
///
/// - http://stackoverflow.com/a/39347461/1342462
///
/// - parameter resumeData: The resume data. This is an opaque data blob produced by `URLSessionDownloadTask`
/// when a task is cancelled. See `URLSession -downloadTask(withResumeData:)` for
/// additional information.
@@ -372,23 +397,43 @@ open class SessionManager {
{
do {
let task = try downloadable.task(session: session, adapter: adapter, queue: queue)
let request = DownloadRequest(session: session, requestTask: .download(downloadable, task))
let download = DownloadRequest(session: session, requestTask: .download(downloadable, task))
request.downloadDelegate.destination = destination
download.downloadDelegate.destination = destination
delegate[task] = request
delegate[task] = download
if startRequestsImmediately { request.resume() }
if startRequestsImmediately { download.resume() }
return request
return download
} catch {
return download(failedWith: error)
return download(downloadable, to: destination, failedWith: error)
}
}
private func download(failedWith error: Error) -> DownloadRequest {
let download = DownloadRequest(session: session, requestTask: .download(nil, nil), error: error)
if startRequestsImmediately { download.resume() }
private func download(
_ downloadable: DownloadRequest.Downloadable?,
to destination: DownloadRequest.DownloadFileDestination?,
failedWith error: Error)
-> DownloadRequest
{
var downloadTask: Request.RequestTask = .download(nil, nil)
if let downloadable = downloadable {
downloadTask = .download(downloadable, nil)
}
let underlyingError = error.underlyingAdaptError ?? error
let download = DownloadRequest(session: session, requestTask: downloadTask, error: underlyingError)
download.downloadDelegate.destination = destination
if let retrier = retrier, error is AdaptError {
allowRetrier(retrier, toRetry: download, with: underlyingError)
} else {
if startRequestsImmediately { download.resume() }
}
return download
}
@@ -418,7 +463,7 @@ open class SessionManager {
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
return upload(fileURL, with: urlRequest)
} catch {
return upload(failedWith: error)
return upload(nil, failedWith: error)
}
}
@@ -436,7 +481,7 @@ open class SessionManager {
let urlRequest = try urlRequest.asURLRequest()
return upload(.file(fileURL, urlRequest))
} catch {
return upload(failedWith: error)
return upload(nil, failedWith: error)
}
}
@@ -464,7 +509,7 @@ open class SessionManager {
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
return upload(data, with: urlRequest)
} catch {
return upload(failedWith: error)
return upload(nil, failedWith: error)
}
}
@@ -482,7 +527,7 @@ open class SessionManager {
let urlRequest = try urlRequest.asURLRequest()
return upload(.data(data, urlRequest))
} catch {
return upload(failedWith: error)
return upload(nil, failedWith: error)
}
}
@@ -510,7 +555,7 @@ open class SessionManager {
let urlRequest = try URLRequest(url: url, method: method, headers: headers)
return upload(stream, with: urlRequest)
} catch {
return upload(failedWith: error)
return upload(nil, failedWith: error)
}
}
@@ -528,7 +573,7 @@ open class SessionManager {
let urlRequest = try urlRequest.asURLRequest()
return upload(.stream(stream, urlRequest))
} catch {
return upload(failedWith: error)
return upload(nil, failedWith: error)
}
}
@@ -614,6 +659,8 @@ open class SessionManager {
let formData = MultipartFormData()
multipartFormData(formData)
var tempFileURL: URL?
do {
var urlRequestWithContentType = try urlRequest.asURLRequest()
urlRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type")
@@ -637,6 +684,8 @@ open class SessionManager {
let fileName = UUID().uuidString
let fileURL = directoryURL.appendingPathComponent(fileName)
tempFileURL = fileURL
var directoryError: Error?
// Create directory inside serial queue to ensure two threads don't do this in parallel
@@ -652,16 +701,37 @@ open class SessionManager {
try formData.writeEncodedData(to: fileURL)
let upload = self.upload(fileURL, with: urlRequestWithContentType)
// Cleanup the temp file once the upload is complete
upload.delegate.queue.addOperation {
do {
try FileManager.default.removeItem(at: fileURL)
} catch {
// No-op
}
}
DispatchQueue.main.async {
let encodingResult = MultipartFormDataEncodingResult.success(
request: self.upload(fileURL, with: urlRequestWithContentType),
request: upload,
streamingFromDisk: true,
streamFileURL: fileURL
)
encodingCompletion?(encodingResult)
}
}
} catch {
// Cleanup the temp file in the event that the multipart form data encoding failed
if let tempFileURL = tempFileURL {
do {
try FileManager.default.removeItem(at: tempFileURL)
} catch {
// No-op
}
}
DispatchQueue.main.async { encodingCompletion?(.failure(error)) }
}
}
@@ -684,13 +754,26 @@ open class SessionManager {
return upload
} catch {
return upload(failedWith: error)
return upload(uploadable, failedWith: error)
}
}
private func upload(failedWith error: Error) -> UploadRequest {
let upload = UploadRequest(session: session, requestTask: .upload(nil, nil), error: error)
if startRequestsImmediately { upload.resume() }
private func upload(_ uploadable: UploadRequest.Uploadable?, failedWith error: Error) -> UploadRequest {
var uploadTask: Request.RequestTask = .upload(nil, nil)
if let uploadable = uploadable {
uploadTask = .upload(uploadable, nil)
}
let underlyingError = error.underlyingAdaptError ?? error
let upload = UploadRequest(session: session, requestTask: uploadTask, error: underlyingError)
if let retrier = retrier, error is AdaptError {
allowRetrier(retrier, toRetry: upload, with: underlyingError)
} else {
if startRequestsImmediately { upload.resume() }
}
return upload
}
@@ -709,6 +792,7 @@ open class SessionManager {
///
/// - returns: The created `StreamRequest`.
@discardableResult
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
open func stream(withHostName hostName: String, port: Int) -> StreamRequest {
return stream(.stream(hostName: hostName, port: port))
}
@@ -723,12 +807,14 @@ open class SessionManager {
///
/// - returns: The created `StreamRequest`.
@discardableResult
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
open func stream(with netService: NetService) -> StreamRequest {
return stream(.netService(netService))
}
// MARK: Private - Stream Implementation
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
private func stream(_ streamable: StreamRequest.Streamable) -> StreamRequest {
do {
let task = try streamable.task(session: session, adapter: adapter, queue: queue)
@@ -744,6 +830,7 @@ open class SessionManager {
}
}
@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
private func stream(failedWith error: Error) -> StreamRequest {
let stream = StreamRequest(session: session, requestTask: .stream(nil, nil), error: error)
if startRequestsImmediately { stream.resume() }
@@ -762,6 +849,7 @@ open class SessionManager {
request.delegate.task = task // resets all task delegate data
request.retryCount += 1
request.startTime = CFAbsoluteTimeGetCurrent()
request.endTime = nil
@@ -769,8 +857,31 @@ open class SessionManager {
return true
} catch {
request.delegate.error = error
request.delegate.error = error.underlyingAdaptError ?? error
return false
}
}
private func allowRetrier(_ retrier: RequestRetrier, toRetry request: Request, with error: Error) {
DispatchQueue.utility.async { [weak self] in
guard let strongSelf = self else { return }
retrier.should(strongSelf, retry: request, with: error) { shouldRetry, timeDelay in
guard let strongSelf = self else { return }
guard shouldRetry else {
if strongSelf.startRequestsImmediately { request.resume() }
return
}
let retrySucceeded = strongSelf.retry(request)
if retrySucceeded, let task = request.task {
strongSelf.delegate[task] = request
} else {
if strongSelf.startRequestsImmediately { request.resume() }
}
}
}
}
}
+26 -22
View File
@@ -33,13 +33,16 @@ open class TaskDelegate: NSObject {
/// The serial operation queue used to execute all operations after the task completes.
open let queue: OperationQueue
/// The data returned by the server.
public var data: Data? { return nil }
/// The error generated throughout the lifecyle of the task.
public var error: Error?
var task: URLSessionTask? {
didSet { reset() }
}
var data: Data? { return nil }
var error: Error?
var initialResponseTime: CFAbsoluteTime?
var credential: URLCredential?
var metrics: AnyObject? // URLSessionTaskMetrics
@@ -331,29 +334,30 @@ class DownloadTaskDelegate: TaskDelegate, URLSessionDownloadDelegate {
{
temporaryURL = location
if let destination = destination {
let result = destination(location, downloadTask.response as! HTTPURLResponse)
let destination = result.destinationURL
let options = result.options
guard
let destination = destination,
let response = downloadTask.response as? HTTPURLResponse
else { return }
do {
destinationURL = destination
let result = destination(location, response)
let destinationURL = result.destinationURL
let options = result.options
if options.contains(.removePreviousFile) {
if FileManager.default.fileExists(atPath: destination.path) {
try FileManager.default.removeItem(at: destination)
}
}
self.destinationURL = destinationURL
if options.contains(.createIntermediateDirectories) {
let directory = destination.deletingLastPathComponent()
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
}
try FileManager.default.moveItem(at: location, to: destination)
} catch {
self.error = error
do {
if options.contains(.removePreviousFile), FileManager.default.fileExists(atPath: destinationURL.path) {
try FileManager.default.removeItem(at: destinationURL)
}
if options.contains(.createIntermediateDirectories) {
let directory = destinationURL.deletingLastPathComponent()
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
}
try FileManager.default.moveItem(at: location, to: destinationURL)
} catch {
self.error = error
}
}
+5 -5
View File
@@ -1,20 +1,20 @@
PODS:
- Alamofire (4.0.1)
- Alamofire (4.2.0)
- BRLOptionParser (0.3.1)
- GCDWebServer (3.3.3):
- GCDWebServer/Core (= 3.3.3)
- GCDWebServer/Core (3.3.3)
DEPENDENCIES:
- Alamofire (~> 4.0)
- Alamofire (~> 4.2.0)
- BRLOptionParser (~> 0.3.1)
- GCDWebServer (~> 3.0)
SPEC CHECKSUMS:
Alamofire: 7682d43245de14874acd142ec137b144aa1dd335
Alamofire: aa2e09d871c9160ac53c90e83c68064a94e3dfbe
BRLOptionParser: a03256a8ff003ca1f5376c55f55f210e085a3958
GCDWebServer: 1c39a1f0763e4eb492bee021e4270fce097d3555
PODFILE CHECKSUM: fe577fe89bbdf6636ba715331bf8d97bbbee45bb
PODFILE CHECKSUM: 8e98b2fb2d6be56882a44b2ff9241a800101e1d4
COCOAPODS: 1.1.0.rc.2
COCOAPODS: 1.1.1
+522 -522
View File
File diff suppressed because it is too large Load Diff
@@ -1,4 +1,6 @@
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
FOUNDATION_EXPORT double AlamofireVersionNumber;
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>4.0.1</string>
<string>4.2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
@@ -1,4 +1,6 @@
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
#import "GCDWebServer.h"
#import "GCDWebServerConnection.h"
@@ -23,12 +23,6 @@ case "${TARGETED_DEVICE_FAMILY}" in
;;
esac
realpath() {
DIRECTORY="$(cd "${1%/*}" && pwd)"
FILENAME="${1##*/}"
echo "$DIRECTORY/$FILENAME"
}
install_resource()
{
if [[ "$1" = /* ]] ; then
@@ -70,7 +64,7 @@ EOM
xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
;;
*.xcassets)
ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH")
ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
*)
@@ -93,7 +87,7 @@ then
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
while read line; do
if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
if [[ $line != "${PODS_ROOT}*" ]]; then
XCASSET_FILES+=("$line")
fi
done <<<"$OTHER_XCASSETS"
@@ -1,4 +1,6 @@
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
FOUNDATION_EXPORT double Pods_ShadowsocksX_NGVersionNumber;
@@ -23,12 +23,6 @@ case "${TARGETED_DEVICE_FAMILY}" in
;;
esac
realpath() {
DIRECTORY="$(cd "${1%/*}" && pwd)"
FILENAME="${1##*/}"
echo "$DIRECTORY/$FILENAME"
}
install_resource()
{
if [[ "$1" = /* ]] ; then
@@ -70,7 +64,7 @@ EOM
xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
;;
*.xcassets)
ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH")
ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
*)
@@ -93,7 +87,7 @@ then
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
while read line; do
if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
if [[ $line != "${PODS_ROOT}*" ]]; then
XCASSET_FILES+=("$line")
fi
done <<<"$OTHER_XCASSETS"
@@ -1,4 +1,6 @@
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
FOUNDATION_EXPORT double Pods_ShadowsocksX_NGTestsVersionNumber;
@@ -16,7 +16,7 @@
<key>FooterText</key>
<string>(The MIT License)
Copyright &#169; 2013-2015 Stephen Celis (&lt;stephen@stephencelis.com&gt;)
Copyright © 2013-2015 Stephen Celis (&lt;stephen@stephencelis.com&gt;)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
@@ -23,12 +23,6 @@ case "${TARGETED_DEVICE_FAMILY}" in
;;
esac
realpath() {
DIRECTORY="$(cd "${1%/*}" && pwd)"
FILENAME="${1##*/}"
echo "$DIRECTORY/$FILENAME"
}
install_resource()
{
if [[ "$1" = /* ]] ; then
@@ -70,7 +64,7 @@ EOM
xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm"
;;
*.xcassets)
ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH")
ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH"
XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE")
;;
*)
@@ -93,7 +87,7 @@ then
# Find all other xcassets (this unfortunately includes those of path pods and other targets).
OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d)
while read line; do
if [[ $line != "`realpath $PODS_ROOT`*" ]]; then
if [[ $line != "${PODS_ROOT}*" ]]; then
XCASSET_FILES+=("$line")
fi
done <<<"$OTHER_XCASSETS"
+3 -3
View File
@@ -585,7 +585,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
3545247EFCD033C3FA63EA6C /* [CP] Check Pods Manifest.lock */ = {
@@ -600,7 +600,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
3E819BD46B855EDB116A3C70 /* [CP] Copy Pods Resources */ = {
@@ -660,7 +660,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
D8C2D6AF002916F4095E15E3 /* [CP] Copy Pods Resources */ = {
@@ -14,7 +14,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "79C040AFDDCE1BCBF6D8B5EB0B85887F"
BlueprintIdentifier = "88E9EC28B8B46C3631E6B242B50F4442"
BuildableName = "Alamofire.framework"
BlueprintName = "Alamofire"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@@ -28,7 +28,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7AD154F318B10A340D705FD3003EAAC6"
BlueprintIdentifier = "3CB2B8006B2B1ACAF9ADCA1DC82E2290"
BuildableName = "libBRLOptionParser.a"
BlueprintName = "BRLOptionParser"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@@ -42,7 +42,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "F69966EE760BB16DE7009DBE04D8B18D"
BlueprintIdentifier = "76AB1BA247F8CB57FCB2BA6577D40FE6"
BuildableName = "Pods_ShadowsocksX_NG.framework"
BlueprintName = "Pods-ShadowsocksX-NG"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@@ -56,7 +56,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "9D7253CF594B2D7CB8127F7CCAFF916F"
BlueprintIdentifier = "339CC546E4A1696296EFEDC2FA79ADE0"
BuildableName = "Pods_ShadowsocksX_NGTests.framework"
BlueprintName = "Pods-ShadowsocksX-NGTests"
ReferencedContainer = "container:Pods/Pods.xcodeproj">
@@ -70,7 +70,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3F0FDAFB5467946C22EE9F2EC643E2B0"
BlueprintIdentifier = "05800FAF969AA3CD7F8AEB1C36988B53"
BuildableName = "libPods-proxy_conf_helper.a"
BlueprintName = "Pods-proxy_conf_helper"
ReferencedContainer = "container:Pods/Pods.xcodeproj">