提交 25f35deb 编写于 作者: C Christian Noon

Merge branch 'master' into tvOS

# Conflicts:
#	Alamofire.xcodeproj/project.pbxproj
......@@ -6,8 +6,6 @@ import XCPlayground
XCPSetExecutionShouldContinueIndefinitely()
Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
.responseString { request, response, result in
print(request)
print(response)
debugPrint(result)
.responseJSON { response in
debugPrint(response)
}
Pod::Spec.new do |s|
s.name = 'Alamofire'
s.version = '2.0.0'
s.version = '3.0.0-beta.2'
s.license = 'MIT'
s.summary = 'Elegant HTTP Networking in Swift'
s.homepage = 'https://github.com/Alamofire/Alamofire'
......
......@@ -9,6 +9,9 @@
/* Begin PBXBuildFile section */
4C0B58391B747A4400C0B99C /* ResponseSerializationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0B58381B747A4400C0B99C /* ResponseSerializationTests.swift */; };
4C0B583A1B747A4400C0B99C /* ResponseSerializationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0B58381B747A4400C0B99C /* ResponseSerializationTests.swift */; };
4C0B62511BB1001C009302D3 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0B62501BB1001C009302D3 /* Response.swift */; };
4C0B62521BB1001C009302D3 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0B62501BB1001C009302D3 /* Response.swift */; };
4C0B62531BB1001C009302D3 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0B62501BB1001C009302D3 /* Response.swift */; };
4C0E5BF81B673D3400816CCC /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0E5BF71B673D3400816CCC /* Result.swift */; };
4C0E5BF91B673D3400816CCC /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0E5BF71B673D3400816CCC /* Result.swift */; };
4C1DC8541B68908E00476DE3 /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1DC8531B68908E00476DE3 /* Error.swift */; };
......@@ -27,8 +30,12 @@
4C33A1441B52089C00873DFF /* ServerTrustPolicyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C33A1421B52089C00873DFF /* ServerTrustPolicyTests.swift */; };
4C341BBA1B1A865A00C1B34D /* CacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C341BB91B1A865A00C1B34D /* CacheTests.swift */; };
4C341BBB1B1A865A00C1B34D /* CacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C341BB91B1A865A00C1B34D /* CacheTests.swift */; };
4C4CBE7B1BAF700C0024D659 /* String+AlamofireTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4CBE7A1BAF700C0024D659 /* String+AlamofireTests.swift */; };
4C4CBE7C1BAF700C0024D659 /* String+AlamofireTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4CBE7A1BAF700C0024D659 /* String+AlamofireTests.swift */; };
4C7C8D221B9D0D9000948136 /* NSURLSessionConfiguration+AlamofireTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7C8D211B9D0D9000948136 /* NSURLSessionConfiguration+AlamofireTests.swift */; };
4C7C8D231B9D0D9000948136 /* NSURLSessionConfiguration+AlamofireTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C7C8D211B9D0D9000948136 /* NSURLSessionConfiguration+AlamofireTests.swift */; };
4C80F9F81BB730EF001B46D2 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C0B62501BB1001C009302D3 /* Response.swift */; };
4C80F9F91BB730F6001B46D2 /* String+AlamofireTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C4CBE7A1BAF700C0024D659 /* String+AlamofireTests.swift */; };
4C811F8D1B51856D00E0F59A /* ServerTrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C811F8C1B51856D00E0F59A /* ServerTrustPolicy.swift */; };
4C811F8E1B51856D00E0F59A /* ServerTrustPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C811F8C1B51856D00E0F59A /* ServerTrustPolicy.swift */; };
4C812C3B1B535F220017E0BF /* alamofire-root-ca.cer in Resources */ = {isa = PBXBuildFile; fileRef = 4C812C3A1B535F220017E0BF /* alamofire-root-ca.cer */; };
......@@ -196,6 +203,7 @@
/* Begin PBXFileReference section */
4C0B58381B747A4400C0B99C /* ResponseSerializationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResponseSerializationTests.swift; sourceTree = "<group>"; };
4C0B62501BB1001C009302D3 /* Response.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = "<group>"; };
4C0E5BF71B673D3400816CCC /* Result.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Result.swift; sourceTree = "<group>"; };
4C1DC8531B68908E00476DE3 /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
4C23EB421B327C5B0090E0BC /* MultipartFormData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultipartFormData.swift; sourceTree = "<group>"; };
......@@ -205,6 +213,7 @@
4C33A1241B5207DB00873DFF /* unicorn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = unicorn.png; sourceTree = "<group>"; };
4C33A1421B52089C00873DFF /* ServerTrustPolicyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServerTrustPolicyTests.swift; sourceTree = "<group>"; };
4C341BB91B1A865A00C1B34D /* CacheTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CacheTests.swift; sourceTree = "<group>"; };
4C4CBE7A1BAF700C0024D659 /* String+AlamofireTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+AlamofireTests.swift"; sourceTree = "<group>"; };
4C7C8D211B9D0D9000948136 /* NSURLSessionConfiguration+AlamofireTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSURLSessionConfiguration+AlamofireTests.swift"; sourceTree = "<group>"; };
4C811F8C1B51856D00E0F59A /* ServerTrustPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ServerTrustPolicy.swift; sourceTree = "<group>"; };
4C812C3A1B535F220017E0BF /* alamofire-root-ca.cer */ = {isa = PBXFileReference; lastKnownFileType = file; name = "alamofire-root-ca.cer"; path = "alamofire.org/alamofire-root-ca.cer"; sourceTree = "<group>"; };
......@@ -421,6 +430,7 @@
isa = PBXGroup;
children = (
4C7C8D211B9D0D9000948136 /* NSURLSessionConfiguration+AlamofireTests.swift */,
4C4CBE7A1BAF700C0024D659 /* String+AlamofireTests.swift */,
);
name = Extensions;
sourceTree = "<group>";
......@@ -452,6 +462,7 @@
4CDE2C361AF8932A00BABAE5 /* Manager.swift */,
4CE2724E1AF88FB500F1D59A /* ParameterEncoding.swift */,
4CDE2C391AF899EC00BABAE5 /* Request.swift */,
4C0B62501BB1001C009302D3 /* Response.swift */,
4C0E5BF71B673D3400816CCC /* Result.swift */,
);
name = Core;
......@@ -866,6 +877,7 @@
4CF627081BA7CBF60011A099 /* Error.swift in Sources */,
4CF627131BA7CBF60011A099 /* Validation.swift in Sources */,
4CF6270E1BA7CBF60011A099 /* MultipartFormData.swift in Sources */,
4C80F9F81BB730EF001B46D2 /* Response.swift in Sources */,
4CF627091BA7CBF60011A099 /* Manager.swift in Sources */,
4CF6270F1BA7CBF60011A099 /* ResponseSerialization.swift in Sources */,
4CF6270B1BA7CBF60011A099 /* Request.swift in Sources */,
......@@ -883,6 +895,7 @@
4CF627181BA7CC240011A099 /* RequestTests.swift in Sources */,
4CF627211BA7CC240011A099 /* TLSEvaluationTests.swift in Sources */,
4CF627221BA7CC240011A099 /* UploadTests.swift in Sources */,
4C80F9F91BB730F6001B46D2 /* String+AlamofireTests.swift in Sources */,
4CF6271E1BA7CC240011A099 /* MultipartFormDataTests.swift in Sources */,
4CF627201BA7CC240011A099 /* ServerTrustPolicyTests.swift in Sources */,
4CF627241BA7CC240011A099 /* ValidationTests.swift in Sources */,
......@@ -910,6 +923,7 @@
4CDE2C471AF89FF300BABAE5 /* ResponseSerialization.swift in Sources */,
4C1DC8551B68908E00476DE3 /* Error.swift in Sources */,
4CDE2C381AF8932A00BABAE5 /* Manager.swift in Sources */,
4C0B62521BB1001C009302D3 /* Response.swift in Sources */,
4DD67C251A5C590000ED2280 /* Alamofire.swift in Sources */,
4C23EB441B327C5B0090E0BC /* MultipartFormData.swift in Sources */,
4C811F8E1B51856D00E0F59A /* ServerTrustPolicy.swift in Sources */,
......@@ -930,6 +944,7 @@
4CEC605A1B745C9100E684F4 /* Error.swift in Sources */,
E4202FD21B667AA100C997FB /* ResponseSerialization.swift in Sources */,
E4202FD31B667AA100C997FB /* Manager.swift in Sources */,
4C0B62531BB1001C009302D3 /* Response.swift in Sources */,
4CEC605B1B745C9100E684F4 /* Result.swift in Sources */,
E4202FD41B667AA100C997FB /* Alamofire.swift in Sources */,
E4202FD51B667AA100C997FB /* MultipartFormData.swift in Sources */,
......@@ -950,6 +965,7 @@
4CDE2C461AF89FF300BABAE5 /* ResponseSerialization.swift in Sources */,
4C1DC8541B68908E00476DE3 /* Error.swift in Sources */,
4CDE2C371AF8932A00BABAE5 /* Manager.swift in Sources */,
4C0B62511BB1001C009302D3 /* Response.swift in Sources */,
F897FF4119AA800700AB5182 /* Alamofire.swift in Sources */,
4C23EB431B327C5B0090E0BC /* MultipartFormData.swift in Sources */,
4C811F8D1B51856D00E0F59A /* ServerTrustPolicy.swift in Sources */,
......@@ -967,6 +983,7 @@
4C3238E71B3604DB00FE04AE /* MultipartFormDataTests.swift in Sources */,
4C33A1431B52089C00873DFF /* ServerTrustPolicyTests.swift in Sources */,
4C341BBA1B1A865A00C1B34D /* CacheTests.swift in Sources */,
4C4CBE7B1BAF700C0024D659 /* String+AlamofireTests.swift in Sources */,
4CA028C51B7466C500C84163 /* ResultTests.swift in Sources */,
4CCFA79A1B2BE71600B6F460 /* URLProtocolTests.swift in Sources */,
F86AEFE71AE6A312007D9C76 /* TLSEvaluationTests.swift in Sources */,
......@@ -991,6 +1008,7 @@
4C3238E81B3604DB00FE04AE /* MultipartFormDataTests.swift in Sources */,
4C33A1441B52089C00873DFF /* ServerTrustPolicyTests.swift in Sources */,
4C341BBB1B1A865A00C1B34D /* CacheTests.swift in Sources */,
4C4CBE7C1BAF700C0024D659 /* String+AlamofireTests.swift in Sources */,
4CA028C61B7466C500C84163 /* ResultTests.swift in Sources */,
4CCFA79B1B2BE71600B6F460 /* URLProtocolTests.swift in Sources */,
F829C6BE1A7A950600A2CD59 /* ParameterEncodingTests.swift in Sources */,
......
......@@ -2,13 +2,14 @@
All notable changes to this project will be documented in this file.
`Alamofire` adheres to [Semantic Versioning](http://semver.org/).
#### 2.x Releases
#### 3.x Releases
- `3.0.0` Betas - [3.0.0-beta.1](#300-beta1) | [3.0.0-beta.2](#300-beta2)
- `2.0.x` Releases - [2.0.0](#200)
#### 2.x Releases
- `2.0.x` Releases - [2.0.0](#200) | [2.0.1](#201) | [2.0.2](#202)
- `2.0.0` Betas - [2.0.0-beta.1](#200-beta1) | [2.0.0-beta.2](#200-beta2) | [2.0.0-beta.3](#200-beta3) | [2.0.0-beta.4](#200-beta4)
#### 1.x Releases
- `1.3.x` Releases - [1.3.0](#130) | [1.3.1](#131)
- `1.2.x` Releases - [1.2.0](#120) | [1.2.1](#121) | [1.2.2](#122) | [1.2.3](#123)
- `1.1.x` Releases - [1.1.0](#110) | [1.1.1](#111) | [1.1.2](#112) | [1.1.3](#113) | [1.1.4](#114) | [1.1.5](#115)
......@@ -16,6 +17,110 @@ All notable changes to this project will be documented in this file.
---
## [3.0.0-beta.2](https://github.com/Alamofire/Alamofire/releases/tag/3.0.0-beta.2)
Released on 2015-09-26. All issues associated with this milestone can be found using this
[filter](https://github.com/Alamofire/Alamofire/issues?utf8=✓&q=milestone%3A3.0.0-beta.2).
#### Added
- Tests around the header behavior for redirected requests.
- Added by [Christian Noon](https://github.com/cnoon) in regards to Issue
[#798](https://github.com/Alamofire/Alamofire/issues/798).
- A migration guide for Alamofire 3.0 documenting all API changes.
- Added by [Christian Noon](https://github.com/cnoon).
#### Updated
- `Response` initializer to have `internal` ACL.
- Updated by [Christian Noon](https://github.com/cnoon).
- All sample code in the README to conform to the Alamofire 3.0 APIs.
- Updated by [Christian Noon](https://github.com/cnoon).
- URL percent escaping to only batch on OS's where required improving
overall performance.
- Updated by [Christian Noon](https://github.com/cnoon).
- Basic auth example in the README to compile on Swift 2.0.
- Updated by [David F. Muir V](https://github.com/dfmuir) in Pull Request
[#810](https://github.com/Alamofire/Alamofire/issues/810).
#### Fixed
- Compiler errors in the playground due to the new response serializer APIs.
- Fixed by [Christian Noon](https://github.com/cnoon).
## [3.0.0-beta.1](https://github.com/Alamofire/Alamofire/releases/tag/3.0.0-beta.1)
Released on 2015-09-21. All issues associated with this milestone can be found using this
[filter](https://github.com/Alamofire/Alamofire/issues?utf8=✓&q=milestone%3A3.0.0-beta.1).
#### Added
- A new `Response` struct to simplify response serialization.
- Added by [Christian Noon](https://github.com/cnoon) in Pull Request
[#792](https://github.com/Alamofire/Alamofire/pull/792).
- A new initializer to the `Manager` allowing dependency injection of the
underlying `NSURLSession`.
- Added by [Christian Noon](https://github.com/cnoon) in Pull Request
[#795](https://github.com/Alamofire/Alamofire/pull/795).
- Tests around the new `Manager` initialization methods.
#### Updated
- Result type to take two generic parameters (`Value` and `Error`) where `Error`
conforms to `ErrorType`.
- Updated by [Christian Noon](https://github.com/cnoon) in Pull Request
[#791](https://github.com/Alamofire/Alamofire/pull/791).
- All response serializers to now return the original server data as `NSData?`.
- Updated by [Christian Noon](https://github.com/cnoon) in Pull Request
[#791](https://github.com/Alamofire/Alamofire/pull/791).
- The `TaskDelegate` to store an error as an `NSError` instead of `ErrorType`.
- Updated by [Christian Noon](https://github.com/cnoon) in Pull Request
[#791](https://github.com/Alamofire/Alamofire/pull/791).
- The `ValidationResult` failure case to require an `NSError` instead of `ErrorType`.
- Updated by [Christian Noon](https://github.com/cnoon) in Pull Request
[#791](https://github.com/Alamofire/Alamofire/pull/791).
- All tests around response serialization and `Result` type usage.
- Updated by [Christian Noon](https://github.com/cnoon) in Pull Request
[#791](https://github.com/Alamofire/Alamofire/pull/791).
- All response serializers to use the new `Response` type.
- Updated by [Christian Noon](https://github.com/cnoon) in Pull Request -
[#792](https://github.com/Alamofire/Alamofire/pull/792).
- The designated initializer for a `Manager` to accept a `SessionDelegate` parameter
allowing dependency injection for better background session support.
- Updated by [Christian Noon](https://github.com/cnoon) in Pull Request
[#795](https://github.com/Alamofire/Alamofire/pull/795).
---
## [2.0.2](https://github.com/Alamofire/Alamofire/releases/tag/2.0.2)
Released on 2015-09-20. All issues associated with this milestone can be found using this
[filter](https://github.com/Alamofire/Alamofire/issues?utf8=✓&q=milestone%3A2.0.2).
#### Updated
- The Embedded Framework documentation to include `git init` info.
- Updated by [Christian Noon](https://github.com/cnoon) in regards to Issue
[#782](https://github.com/Alamofire/Alamofire/issues/782).
#### Fixed
- Alamofire iOS framework target by adding Alamofire iOS Tests as Target Dependency.
- Fixed by [Nicky Gerritsen](https://github.com/nickygerritsen) in Pull Request
[#780](https://github.com/Alamofire/Alamofire/pull/780).
- Percent encoding issue for long Chinese strings using URL parameter encoding.
- Fixed by [Christian Noon](https://github.com/cnoon) in regards to Issue
[#206](https://github.com/Alamofire/Alamofire/issues/206).
## [2.0.1](https://github.com/Alamofire/Alamofire/releases/tag/2.0.1)
Released on 2015-09-16. All issues associated with this milestone can be found using this
[filter](https://github.com/Alamofire/Alamofire/issues?utf8=✓&q=milestone%3A2.0.1).
#### Updated
- The CocoaPods installation instructions in the README.
- Updated by [Christian Noon](https://github.com/cnoon).
- The Carthage installation instructions in the README.
- Updated by [Gustavo Barbosa](https://github.com/barbosa) in Pull Request
[#759](https://github.com/Alamofire/Alamofire/pull/759).
#### Fixed
- The link to the 2.0 migration guide in the README.
- Fixed by [Dwight Watson](https://github.com/dwightwatson) in Pull Request
[#750](https://github.com/Alamofire/Alamofire/pull/750).
- Issue where NTLM authentication credentials were not used for authentication challenges.
- Fixed by [Christian Noon](https://github.com/cnoon) in regards to Issue
[#721](https://github.com/Alamofire/Alamofire/pull/721).
## [2.0.0](https://github.com/Alamofire/Alamofire/releases/tag/2.0.0)
Released on 2015-09-09. All issues associated with this milestone can be found using this
[filter](https://github.com/Alamofire/Alamofire/issues?utf8=✓&q=milestone%3A2.0.0).
......
# Alamofire 3.0 Migration Guide
Alamofire 3.0 is the latest major release of Alamofire, an HTTP networking library for iOS, Mac OS X and watchOS written in Swift. As a major release, following Semantic Versioning conventions, 3.0 introduces several API-breaking changes that one should be aware of.
This guide is provided in order to ease the transition of existing applications using Alamofire 2.x to the latest APIs, as well as explain the design and structure of new and changed functionality.
## Requirements
Alamofire 3.0 officially supports iOS 8+, Mac OS X 10.9+, watchOS 2.0, Xcode 7 and Swift 2.0. If you'd like to use Alamofire in a project targeting iOS 7 and Swift 1.x, use the latest tagged 1.x release.
## Reasons for Bumping to 3.0
The [Alamofire Software Foundation](https://github.com/Alamofire/Foundation) (ASF) tries to do everything possible to avoid MAJOR version bumps. We realize the challenges involved with migrating large projects from one MAJOR version to another. With that said, we also want to make sure we're always producing the highest quality APIs and features possible.
After releasing Alamofire 2.0, it became clear that the response serialization system still had some room for improvement. After much debate, we decided to strictly follow semver and move forward with all the core logic changes becoming Alamofire 3.0. We've also made some fairly significant changes that should give us more flexibility moving forward to help avoid the need for MAJOR version bumps to maintain backwards compatibility.
## Benefits of Upgrading
The benefits of upgrading can be summarized as follows:
* No more casting a response serializer `error` from an `ErrorType` to an `NSError`.
* Original server data is now ALWAYS returned in all response serializers regardless of whether the result was a `.Success` or `.Failure`.
* Custom response serializers are now ALWAYS called regardless of whether an `error` occurred.
* Custom response serializers are now passed in the `error` allowing you to switch between different parsing schemes if necessary.
* Custom response serializers can now wrap up any Alamofire `NSError` into a `CustomError` type of your choosing.
* `Manager` initialization can now accept custom `NSURLSession` or `SessionDelegate` objects using dependency injection.
---
## Breaking API Changes
Alamofire 3.0 contains some breaking API changes to the foundational classes supporting the response serialization system. It is important to understand how these changes affect the common usage patterns.
### Result Type
The `Result` type was introduced in Alamofire 2.0 as a single generic parameter with the following signature:
```swift
public enum Result<Value> {
case Success(Value)
case Failure(NSData?, ErrorType)
}
```
While this was a significant improvement on the behavior of Alamofire 1.0, there was still room for improvement. By defining the `.Failure` case to take an `ErrorType`, all consumers needed to cast the `ErrorType` to some concrete object such as an `NSError` before being able to interact with it. This was certainly not ideal. Additionally, by only allowing the `NSData?` from the server to be appended in a `.Failure` case, it was not possible to access the original server data in a `.Success` case.
In Alamofire 3.0, the `Result` type has been redesigned to be a double generic type that does not store the `NSData?` in the `.Failure` case.
```swift
public enum Result<Value, Error: ErrorType> {
case Success(Value)
case Failure(Error)
}
```
These changes allow Alamofire to return the original server data in both cases. It also removes the requirement of having to cast the `ErrorType` when working with the `.Failure` case error object.
### Response
In order to avoid constantly having to change the response serializer completion closure signatures, ALamofire 3.0 introduces a `Response` struct. All response serializers (with the exception of `response`) return a generic `Response` struct.
```swift
public struct Response<Value, Error: ErrorType> {
/// The URL request sent to the server.
public let request: NSURLRequest?
/// The server's response to the URL request.
public let response: NSHTTPURLResponse?
/// The data returned by the server.
public let data: NSData?
/// The result of response serialization.
public let result: Result<Value, Error>
}
```
This unifies the signature of all response serializer completion closures by only needing to specify a single parameter rather than three or four. If another major release of Alamofire needs to modify the signature, thankfully the number of parameters in all response serializers will NOT need to change. Given the fact that the Swift compiler can present some fairly misleading compiler errors when the arguments are not correct, this should help alleviate some painful updates between MAJOR version bumps of Alamofire.
### Response Serializers
The biggest change in Alamofire 3.0 are the response serializers. They are now powered by the new `Response` struct and updated `Result` type. These two generic classes make it VERY easy to interact with the response serializers in a consistent, type-safe manner.
```swift
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.responseJSON { response in
debugPrint(response) // prints detailed description of all response properties
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
```
Besides the single response parameter in the completion closure, the other major callouts are that the original server data is always available whether the `Result` was a `.Success` or `.Failure`. Additionally, both the `value` and `error` of the `Result` type are strongly typed objects thanks to the power of generics. All default response serializer errors will be an `NSError` type. Custom response serializers can specify any custom `ErrorType`.
#### Response Serializer Type
For those wishing to create custom response serializer types, you'll need to familiarize yourself with the new `ResponseSerializerType` protocol and generic `ResponseSerializer` struct.
```swift
public protocol ResponseSerializerType {
/// The type of serialized object to be created by this `ResponseSerializerType`.
typealias SerializedObject
/// The type of error to be created by this `ResponseSerializer` if serialization fails.
typealias ErrorObject: ErrorType
/**
A closure used by response handlers that takes a request, response, data and error and returns a result.
*/
var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result<SerializedObject, ErrorObject> { get }
}
```
All the possible information about the `Request` is now passed into the `serializeResponse` closure. In Alamofire 3.0, the `serializeResponse` closure is ALWAYS called whether an error occurred or not. This is for several reasons.
1. Passing the error into the response serializer allows the implementation to switch parsing schemes based on what error occurred. For example, some APIs will return different payload schemas when certain errors occur. The new design allows you to switch on the error type and use different parsing logic.
2. Any error produced by Alamofire will always be an `NSError`. If your custom response serializer returns `CustomError` types, then the `NSError` returned by Alamofire must be converted into a `CustomError` type. This makes it MUCH easier to wrap Alamofire errors in your own `CustomError` type objects.
> This is also required for all the generics logic to work properly.
### Validation Result
The `ValidationResult` enumeration in Alamofire 3.0 has been updated to take an `NSError` in the `.Failure` case. The reasoning for this change is that all Alamofire errors generated need to be `NSError` types. If not, it introduces the need to cast all error objects coming from Alamofire at the response serializer level.
```swift
public enum ValidationResult {
case Success
case Failure(NSError)
}
```
> If you are extending the `Request` type in any way that can produce an error, that error always needs to be of type `NSError`. If you'd like to wrap the error into a `CustomError` type, it should be wrapped in a custom response serializer implementation.
---
## New Features
### Dependency Injection
Alamofire 3.0 leverages [dependency injection](https://en.wikipedia.org/wiki/Dependency_injection) to allow some powerful new customizations to take place for the URL session and delegate.
#### Session Delegate
In previous versions of Alamofire, the `SessionDelegate` was automatically created by the `Manager` instance. While this is convenient, it can be problematic for background sessions. One may need to hook up the task override closures before instantiating the URL session. Otherwise the URL session delegate could be called before the task override closures are able to be set.
In Alamofire 3.0, the `Manager` initializer adds the ability to provide a custom `SessionDelegate` object with the task override closures already set using dependency injection. This greatly increases the flexibility of Alamofire in regards to background sessions.
```swift
public init(
configuration: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration(),
delegate: SessionDelegate = SessionDelegate(),
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
{
self.delegate = delegate
self.session = NSURLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
}
```
#### URL Session
Alamofire 3.0 also adds the ability to use dependency injection to provide a custom `NSURLSession` to the `Manager` instance. This provides complete control over the URL session initialization if you need it allowing `NSURLSession` subclasses for various kinds of testing and DVR implementations.
```swift
public init?(
session: NSURLSession,
delegate: SessionDelegate,
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
{
self.delegate = delegate
self.session = session
guard delegate === session.delegate else { return nil }
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
}
```
> We're very excited to see what the community comes up with given these new possibilities with Alamofire 3.0.
......@@ -75,11 +75,11 @@ class DetailViewController: UITableViewController {
refreshControl?.beginRefreshing()
let start = CACurrentMediaTime()
request.responseString { request, response, result in
request.responseString { response in
let end = CACurrentMediaTime()
self.elapsedTime = end - start
if let response = response {
if let response = response.response {
for (field, value) in response.allHeaderFields {
self.headers["\(field)"] = "\(value)"
}
......@@ -88,7 +88,7 @@ class DetailViewController: UITableViewController {
if let segueIdentifier = self.segueIdentifier {
switch segueIdentifier {
case "GET", "POST", "PUT", "DELETE":
self.body = result.value
self.body = response.result.value
case "DOWNLOAD":
self.body = self.downloadedBodyString()
default:
......
......@@ -29,6 +29,7 @@ Alamofire is an HTTP networking library written in Swift.
## Migration Guides
- [Alamofire 3.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%203.0%20Migration%20Guide.md)
- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md)
## Communication
......@@ -94,7 +95,13 @@ If you prefer not to use either of the aforementioned dependency managers, you c
#### Embedded Framework
- Add Alamofire as a [submodule](http://git-scm.com/docs/git-submodule) by opening the Terminal, `cd`-ing into your top-level project directory, and entering the following command:
- 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
$ git init
```
- Add Alamofire as a git [submodule](http://git-scm.com/docs/git-submodule) by running the following command:
```bash
$ git submodule add https://github.com/Alamofire/Alamofire.git
......@@ -118,7 +125,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.
---
......@@ -136,11 +143,16 @@ Alamofire.request(.GET, "http://httpbin.org/get")
```swift
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.response { request, response, data, error in
print(request)
print(response)
print(error)
}
.responseJSON { response in
print(response.request) // original URL request
print(response.response) // URL response
print(response.data) // server data
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}
```
> Networking in Alamofire is done _asynchronously_. Asynchronous programming may be a source of frustration to programmers unfamiliar with the concept, but there are [very good reasons](https://developer.apple.com/library/ios/qa/qa1693/_index.html) for doing it this way.
......@@ -152,27 +164,52 @@ Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
**Built-in Response Methods**
- `response()`
- `responseData()`
- `responseString(encoding: NSStringEncoding)`
- `responseJSON(options: NSJSONReadingOptions)`
- `responsePropertyList(options: NSPropertyListReadOptions)`
#### Response String Handler
#### Response Handler
```swift
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.response { request, response, data, error in
print(request)
print(response)
print(data)
print(error)
}
```
> The `response` serializer does NOT evaluate any of the response data. It merely forwards on all the information directly from the URL session delegate. We strongly encourage you to leverage the other responser serializers taking advantage of `Response` and `Result` types.
#### Response Data Handler
```swift
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.responseData { response in
print(response.request)
print(response.response)
print(response.result)
}
```
#### Response String Handler
```swift
Alamofire.request(.GET, "http://httpbin.org/get")
.responseString { _, _, result in
print("Success: \(result.isSuccess)")
print("Response String: \(result.value)")
.responseString { response in
print("Success: \(response.result.isSuccess)")
print("Response String: \(response.result.value)")
}
```
#### Response JSON Handler
#### Response JSON Handler
```swift
Alamofire.request(.GET, "http://httpbin.org/get")
.responseJSON { _, _, result in
print(result)
debugPrint(result)
.responseJSON { response in
debugPrint(response)
}
```
......@@ -182,11 +219,11 @@ Response handlers can even be chained:
```swift
Alamofire.request(.GET, "http://httpbin.org/get")
.responseString { _, _, result in
print("Response String: \(result.value)")
.responseString { response in
print("Response String: \(response.result.value)")
}
.responseJSON { _, _, result in
print("Response JSON: \(result.value)")
.responseJSON { response in
print("Response JSON: \(response.result.value)")
}
```
......@@ -263,7 +300,7 @@ enum ParameterEncoding {
```swift
let URL = NSURL(string: "http://httpbin.org/get")!
var request = NSURLRequest(URL: URL)
var request = NSMutableURLRequest(URL: URL)
let parameters = ["foo": "bar"]
let encoding = Alamofire.ParameterEncoding.URL
......@@ -297,8 +334,8 @@ let headers = [
]
Alamofire.request(.GET, "http://httpbin.org/get", headers: headers)
.responseJSON { _, _, result in
debugPrint(result)
.responseJSON { response in
debugPrint(response)
}
```
......@@ -331,12 +368,12 @@ Alamofire.upload(.POST, "http://httpbin.org/post", file: fileURL)
// This closure is NOT called on the main queue for performance
// reasons. To update your ui, dispatch to the main queue.
dispatch_async(dispatch_get_main_queue) {
dispatch_async(dispatch_get_main_queue()) {
print("Total bytes written on main queue: \(totalBytesWritten)")
}
}
.responseJSON { request, response, result in
debugPrint(result)
.responseJSON { response in
debugPrint(response)
}
```
......@@ -345,7 +382,7 @@ Alamofire.upload(.POST, "http://httpbin.org/post", file: fileURL)
```swift
Alamofire.upload(
.POST,
URLString: "http://httpbin.org/post",
"http://httpbin.org/post",
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(fileURL: unicornImageURL, name: "unicorn")
multipartFormData.appendBodyPart(fileURL: rainbowImageURL, name: "rainbow")
......@@ -353,8 +390,8 @@ Alamofire.upload(
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { request, response, result in
debugPrint(result)
upload.responseJSON { response in
debugPrint(response)
}
case .Failure(let encodingError):
print(encodingError)
......@@ -404,7 +441,7 @@ Alamofire.download(.GET, "http://httpbin.org/stream/100", destination: destinati
print("Total bytes read on main queue: \(totalBytesRead)")
}
}
.response { request, response, _, error in
.responseData { response in
print(response)
}
```
......@@ -413,9 +450,9 @@ Alamofire.download(.GET, "http://httpbin.org/stream/100", destination: destinati
```swift
Alamofire.download(.GET, "http://httpbin.org/stream/100", destination: destination)
.response { request, response, data, error in
.responseData { response in
if let
data = data,
data = response.data,
resumeDataString = NSString(data: data, encoding: NSUTF8StringEncoding)
{
print("Resume Data: \(resumeDataString)")
......@@ -429,10 +466,10 @@ Alamofire.download(.GET, "http://httpbin.org/stream/100", destination: destinati
```swift
let download = Alamofire.download(.GET, "http://httpbin.org/stream/100", destination: destination)
download.response { request, response, data, error in
download.responseData { _ in
if let
resumeData = download.resumeData,
resumeDataString = NSString(data: data, encoding: NSUTF8StringEncoding)
resumeDataString = NSString(data: resumeData, encoding: NSUTF8StringEncoding)
{
print("Resume Data: \(resumeDataString)")
} else {
......@@ -462,8 +499,8 @@ let password = "password"
Alamofire.request(.GET, "https://httpbin.org/basic-auth/\(user)/\(password)")
.authenticate(user: user, password: password)
.response { request, response, _, error in
print(response)
.responseJSON { response in
debugPrint(response)
}
```
......@@ -474,13 +511,13 @@ let user = "user"
let password = "password"
let credentialData = "\(user):\(password)".dataUsingEncoding(NSUTF8StringEncoding)!
let base64Credentials = credentialData.base64EncodedStringWithOptions(nil)
let base64Credentials = credentialData.base64EncodedStringWithOptions([])
let headers = ["Authorization": "Basic \(base64Credentials)"]
Alamofire.request(.GET, "http://httpbin.org/basic-auth/user/password", headers: headers)
.responseJSON { _, _, result in
print(result)
.responseJSON { response in
debugPrint(response)
}
```
......@@ -494,8 +531,8 @@ let credential = NSURLCredential(user: user, password: password, persistence: .F
Alamofire.request(.GET, "https://httpbin.org/basic-auth/\(user)/\(password)")
.authenticate(usingCredential: credential)
.response { request, response, _, error in
print(response)
.responseJSON { response in
debugPrint(response)
}
```
......@@ -509,8 +546,8 @@ By default, Alamofire treats any completed request to be successful, regardless
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.response { _, _, _, error in
print(error)
.response { response in
print(response)
}
```
......@@ -521,11 +558,11 @@ Automatically validates status code within `200...299` range, and that the `Cont
```swift
Alamofire.request(.GET, "http://httpbin.org/get", parameters: ["foo": "bar"])
.validate()
.responseJSON { _, _, result in
switch result {
.responseJSON { response in
switch response.result {
case .Success:
print("Validation Successful")
case .Failure(_, let error):
case .Failure(let error):
print(error)
}
}
......@@ -584,7 +621,7 @@ Alamofire.request(.GET, "http://httpbin.org/get")
```swift
let manager = Alamofire.Manager.sharedInstance
manager.request(NSURLRequest(URL: NSURL(string: "http://httpbin.org/get")))
manager.request(NSURLRequest(URL: NSURL(string: "http://httpbin.org/get")!))
```
Applications can create managers for background and ephemeral sessions, as well as new managers that customize the default session configuration, such as for default headers (`HTTPAdditionalHeaders`) or timeout interval (`timeoutIntervalForRequest`).
......@@ -628,7 +665,7 @@ let manager = Alamofire.Manager(configuration: configuration)
The result of a `request`, `upload`, or `download` method is an instance of `Alamofire.Request`. A request is always created using a constructor method from an owning manager, and never initialized directly.
Methods like `authenticate`, `validate`, and `response` return the caller in order to facilitate chaining.
Methods like `authenticate`, `validate` and `responseData` return the caller in order to facilitate chaining.
Requests can be suspended, resumed, and cancelled:
......@@ -646,24 +683,26 @@ For example, here's how a response handler using [Ono](https://github.com/mattt/
```swift
extension Request {
public static func XMLResponseSerializer() -> GenericResponseSerializer<ONOXMLDocument> {
return GenericResponseSerializer { request, response, data in
public static func XMLResponseSerializer() -> ResponseSerializer<ONOXMLDocument, NSError> {
return ResponseSerializer { request, response, data, error in
guard error == nil else { return .Failure(error!) }
guard let validData = data else {
let failureReason = "Data could not be serialized. Input data was nil."
let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
return .Failure(data, error)
return .Failure(error)
}
do {
let XML = try ONOXMLDocument(data: validData)
return .Success(XML)
} catch {
return .Failure(data, error as NSError)
return .Failure(error as NSError)
}
}
}
public func responseXMLDocument(completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<ONOXMLDocument>) -> Void) -> Self {
public func responseXMLDocument(completionHandler: Response<ONOXMLDocument, NSError> -> Void) -> Self {
return response(responseSerializer: Request.XMLResponseSerializer(), completionHandler: completionHandler)
}
}
......@@ -679,10 +718,12 @@ public protocol ResponseObjectSerializable {
}
extension Request {
public func responseObject<T: ResponseObjectSerializable>(completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<T>) -> Void) -> Self {
let responseSerializer = GenericResponseSerializer<T> { request, response, data in
public func responseObject<T: ResponseObjectSerializable>(completionHandler: Response<T, NSError> -> Void) -> Self {
let responseSerializer = ResponseSerializer<T, NSError> { request, response, data, error in
guard error == nil else { return .Failure(error!) }
let JSONResponseSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
let result = JSONResponseSerializer.serializeResponse(request, response, data)
let result = JSONResponseSerializer.serializeResponse(request, response, data, error)
switch result {
case .Success(let value):
......@@ -694,10 +735,10 @@ extension Request {
} else {
let failureReason = "JSON could not be serialized into response object: \(value)"
let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
return .Failure(data, error)
return .Failure(error)
}
case .Failure(let data, let error):
return .Failure(data, error)
case .Failure(let error):
return .Failure(error)
}
}
......@@ -719,9 +760,9 @@ final class User: ResponseObjectSerializable {
```
```swift
Alamofire.request(.GET, "http://example.com/users/mattt")
.responseObject { (_, _, result: Result<User>) in
debugPrint(result)
Alamofire.request(.GET, "https://example.com/users/mattt")
.responseObject { (response: Response<User, NSError>) in
debugPrint(response)
}
```
......@@ -733,10 +774,12 @@ public protocol ResponseCollectionSerializable {
}
extension Alamofire.Request {
public func responseCollection<T: ResponseCollectionSerializable>(completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<[T]>) -> Void) -> Self {
let responseSerializer = GenericResponseSerializer<[T]> { request, response, data in
public func responseCollection<T: ResponseCollectionSerializable>(completionHandler: Response<[T], NSError> -> Void) -> Self {
let responseSerializer = ResponseSerializer<[T], NSError> { request, response, data, error in
guard error == nil else { return .Failure(error!) }
let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
let result = JSONSerializer.serializeResponse(request, response, data)
let result = JSONSerializer.serializeResponse(request, response, data, error)
switch result {
case .Success(let value):
......@@ -745,10 +788,10 @@ extension Alamofire.Request {
} else {
let failureReason = "Response collection could not be serialized due to nil response"
let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
return .Failure(data, error)
return .Failure(error)
}
case .Failure(let data, let error):
return .Failure(data, error)
case .Failure(let error):
return .Failure(error)
}
}
......@@ -785,8 +828,8 @@ final class User: ResponseObjectSerializable, ResponseCollectionSerializable {
```swift
Alamofire.request(.GET, "http://example.com/users")
.responseCollection { (_, _, result: Result<[User]>) in
debugPrint(result)
.responseCollection { (response: Response<[User], NSError>) in
debugPrint(response)
}
```
......@@ -989,7 +1032,6 @@ let serverTrustPolicies: [String: ServerTrustPolicy] = [
]
let manager = Manager(
configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)
```
......@@ -1051,6 +1093,8 @@ The following rdars have some affect on the current implementation of Alamofire.
* [rdar://21349340](http://www.openradar.me/radar?id=5517037090635776) - Compiler throwing warning due to toll-free bridging issue in test case
* [rdar://22307360](http://www.openradar.me/radar?id=4895563208196096) - Swift #available check not working properly with min deployment target
> Resolved in Xcode 7.1 beta 2. Will remove once Xcode 7.1 is out of beta.
## FAQ
### What's the origin of the name Alamofire?
......
......@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.0</string>
<string>3.0.0-beta.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
......
......@@ -114,10 +114,12 @@ public class Manager {
// MARK: - Lifecycle
/**
Initializes the `Manager` instance with the given configuration and server trust policy.
Initializes the `Manager` instance with the specified configuration, delegate and server trust policy.
- parameter configuration: The configuration used to construct the managed session.
`NSURLSessionConfiguration.defaultSessionConfiguration()` by default.
- parameter delegate: The delegate used when initializing the session. `SessionDelegate()` by
default.
- parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust
challenges. `nil` by default.
......@@ -125,13 +127,42 @@ public class Manager {
*/
public init(
configuration: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration(),
delegate: SessionDelegate = SessionDelegate(),
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
{
self.delegate = SessionDelegate()
self.session = NSURLSession(configuration: configuration, delegate: self.delegate, delegateQueue: nil)
self.session.serverTrustPolicyManager = serverTrustPolicyManager
self.delegate = delegate
self.session = NSURLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
self.delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
}
/**
Initializes the `Manager` instance with the specified session, delegate and server trust policy.
- parameter session: The URL session.
- parameter delegate: The delegate of the URL session. Must equal the URL session's delegate.
- parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust
challenges. `nil` by default.
- returns: The new `Manager` instance if the URL session's delegate matches the delegate parameter.
*/
public init?(
session: NSURLSession,
delegate: SessionDelegate,
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
{
self.delegate = delegate
self.session = session
guard delegate === session.delegate else { return nil }
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
}
private func commonInit(serverTrustPolicyManager serverTrustPolicyManager: ServerTrustPolicyManager?) {
session.serverTrustPolicyManager = serverTrustPolicyManager
delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in
guard let strongSelf = self else { return }
dispatch_async(dispatch_get_main_queue()) { strongSelf.backgroundCompletionHandler?() }
}
......@@ -219,6 +250,15 @@ public class Manager {
}
}
/**
Initializes the `SessionDelegate` instance.
- returns: The new `SessionDelegate` instance.
*/
public override init() {
super.init()
}
// MARK: - NSURLSessionDelegate
// MARK: Override Closures
......@@ -645,5 +685,24 @@ public class Manager {
var _streamTaskWriteClosed: Any?
var _streamTaskBetterRouteDiscovered: Any?
var _streamTaskDidBecomeInputStream: Any?
// MARK: - NSObject
public override func respondsToSelector(selector: Selector) -> Bool {
switch selector {
case "URLSession:didBecomeInvalidWithError:":
return sessionDidBecomeInvalidWithError != nil
case "URLSession:didReceiveChallenge:completionHandler:":
return sessionDidReceiveChallenge != nil
case "URLSessionDidFinishEventsForBackgroundURLSession:":
return sessionDidFinishEventsForBackgroundURLSession != nil
case "URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:":
return taskWillPerformHTTPRedirection != nil
case "URLSession:dataTask:didReceiveResponse:completionHandler:":
return dataTaskDidReceiveResponse != nil
default:
return self.dynamicType.instancesRespondToSelector(selector)
}
}
}
}
......@@ -31,7 +31,7 @@ public enum Method: String {
case OPTIONS, GET, HEAD, POST, PUT, PATCH, DELETE, TRACE, CONNECT
}
// MARK: - ParameterEncoding
// MARK: ParameterEncoding
/**
Used to specify the way in which a set of parameters are applied to a URL request.
......@@ -212,6 +212,38 @@ public enum ParameterEncoding {
let allowedCharacterSet = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet
allowedCharacterSet.removeCharactersInString(generalDelimitersToEncode + subDelimitersToEncode)
return string.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) ?? ""
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 Chinense 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, OSX 10.10, *) {
escaped = string.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) ?? string
} else {
let batchSize = 50
var index = string.startIndex
while index != string.endIndex {
let startIndex = index
let endIndex = index.advancedBy(batchSize, limit: string.endIndex)
let range = Range(start: startIndex, end: endIndex)
let substring = string.substringWithRange(range)
escaped += substring.stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacterSet) ?? substring
index = endIndex
}
}
return escaped
}
}
......@@ -193,7 +193,7 @@ public class Request {
let progress: NSProgress
var data: NSData? { return nil }
var error: ErrorType?
var error: NSError?
var credential: NSURLCredential?
......
// Response.swift
//
// Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/)
//
// 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 the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
/// Used to store all response data returned from a completed `Request`.
public struct Response<Value, Error: ErrorType> {
/// The URL request sent to the server.
public let request: NSURLRequest?
/// The server's response to the URL request.
public let response: NSHTTPURLResponse?
/// The data returned by the server.
public let data: NSData?
/// The result of response serialization.
public let result: Result<Value, Error>
/**
Initializes the `Response` instance with the specified URL request, URL response, server data and response
serialization result.
- parameter request: The URL request sent to the server.
- parameter response: The server's response to the URL request.
- parameter data: The data returned by the server.
- parameter result: The result of response serialization.
- returns: the new `Response` instance.
*/
init(request: NSURLRequest?, response: NSHTTPURLResponse?, data: NSData?, result: Result<Value, Error>) {
self.request = request
self.response = response
self.data = data
self.result = result
}
}
// MARK: - CustomStringConvertible
extension Response: CustomStringConvertible {
/// The textual representation used when written to an output stream, which includes whether the result was a
/// success or failure.
public var description: String {
return result.debugDescription
}
}
// MARK: - CustomDebugStringConvertible
extension Response: CustomDebugStringConvertible {
/// The debug textual representation used when written to an output stream, which includes the URL request, the URL
/// response, the server data and the response serialization result.
public var debugDescription: String {
var output: [String] = []
output.append(request != nil ? "[Request]: \(request!)" : "[Request]: nil")
output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil")
output.append("[Data]: \(data?.length ?? 0) bytes")
output.append("[Result]: \(result.debugDescription)")
return output.joinWithSeparator("\n")
}
}
......@@ -27,38 +27,44 @@ import Foundation
/**
The type in which all response serializers must conform to in order to serialize a response.
*/
public protocol ResponseSerializer {
/// The type of serialized object to be created by this `ResponseSerializer`.
public protocol ResponseSerializerType {
/// The type of serialized object to be created by this `ResponseSerializerType`.
typealias SerializedObject
/// The type of error to be created by this `ResponseSerializer` if serialization fails.
typealias ErrorObject: ErrorType
/**
A closure used by response handlers that takes a request, response, and data and returns a result.
A closure used by response handlers that takes a request, response, data and error and returns a result.
*/
var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?) -> Result<SerializedObject> { get }
var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result<SerializedObject, ErrorObject> { get }
}
// MARK: -
/**
A generic `ResponseSerializer` used to serialize a request, response, and data into a serialized object.
A generic `ResponseSerializerType` used to serialize a request, response, and data into a serialized object.
*/
public struct GenericResponseSerializer<T>: ResponseSerializer {
public struct ResponseSerializer<Value, Error: ErrorType>: ResponseSerializerType {
/// The type of serialized object to be created by this `ResponseSerializer`.
public typealias SerializedObject = T
public typealias SerializedObject = Value
/// The type of error to be created by this `ResponseSerializer` if serialization fails.
public typealias ErrorObject = Error
/**
A closure used by response handlers that takes a request, response, and data and returns a result.
A closure used by response handlers that takes a request, response, data and error and returns a result.
*/
public var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?) -> Result<SerializedObject>
public var serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result<Value, Error>
/**
Initializes the `GenericResponseSerializer` instance with the given serialize response closure.
Initializes the `ResponseSerializer` instance with the given serialize response closure.
- parameter serializeResponse: The closure used to serialize the response.
- returns: The new generic response serializer instance.
*/
public init(serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?) -> Result<SerializedObject>) {
public init(serializeResponse: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Result<Value, Error>) {
self.serializeResponse = serializeResponse
}
}
......@@ -77,7 +83,7 @@ extension Request {
*/
public func response(
queue queue: dispatch_queue_t? = nil,
completionHandler: (NSURLRequest?, NSHTTPURLResponse?, NSData?, ErrorType?) -> Void)
completionHandler: (NSURLRequest?, NSHTTPURLResponse?, NSData?, NSError?) -> Void)
-> Self
{
delegate.queue.addOperationWithBlock {
......@@ -99,23 +105,29 @@ extension Request {
- returns: The request.
*/
public func response<T: ResponseSerializer, V where T.SerializedObject == V>(
public func response<T: ResponseSerializerType>(
queue queue: dispatch_queue_t? = nil,
responseSerializer: T,
completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<V>) -> Void)
completionHandler: Response<T.SerializedObject, T.ErrorObject> -> Void)
-> Self
{
delegate.queue.addOperationWithBlock {
let result: Result<T.SerializedObject> = {
if let error = self.delegate.error {
return .Failure(self.delegate.data, error)
} else {
return responseSerializer.serializeResponse(self.request, self.response, self.delegate.data)
}
}()
let result = responseSerializer.serializeResponse(
self.request,
self.response,
self.delegate.data,
self.delegate.error
)
dispatch_async(queue ?? dispatch_get_main_queue()) {
completionHandler(self.request, self.response, result)
let response = Response<T.SerializedObject, T.ErrorObject>(
request: self.request,
response: self.response,
data: self.delegate.data,
result: result
)
completionHandler(response)
}
}
......@@ -132,12 +144,14 @@ extension Request {
- returns: A data response serializer.
*/
public static func dataResponseSerializer() -> GenericResponseSerializer<NSData> {
return GenericResponseSerializer { _, _, data in
guard let validData = data else {
let failureReason = "Data could not be serialized. Input data was nil."
public static func dataResponseSerializer() -> ResponseSerializer<NSData, NSError> {
return ResponseSerializer { _, _, data, error in
guard error == nil else { return .Failure(error!) }
guard let validData = data where validData.length > 0 else {
let failureReason = "Data could not be serialized. Input data was nil or zero length."
let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
return .Failure(data, error)
return .Failure(error)
}
return .Success(validData)
......@@ -151,7 +165,7 @@ extension Request {
- returns: The request.
*/
public func responseData(completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<NSData>) -> Void) -> Self {
public func responseData(completionHandler: Response<NSData, NSError> -> Void) -> Self {
return response(responseSerializer: Request.dataResponseSerializer(), completionHandler: completionHandler)
}
}
......@@ -171,13 +185,15 @@ extension Request {
*/
public static func stringResponseSerializer(
var encoding encoding: NSStringEncoding? = nil)
-> GenericResponseSerializer<String>
-> ResponseSerializer<String, NSError>
{
return GenericResponseSerializer { _, response, data in
guard let validData = data else {
let failureReason = "String could not be serialized because input data was nil."
return ResponseSerializer { _, response, data, error in
guard error == nil else { return .Failure(error!) }
guard let validData = data where validData.length > 0 else {
let failureReason = "String could not be serialized. Input data was nil or zero length."
let error = Error.errorWithCode(.StringSerializationFailed, failureReason: failureReason)
return .Failure(data, error)
return .Failure(error)
}
if let encodingName = response?.textEncodingName where encoding == nil {
......@@ -193,7 +209,7 @@ extension Request {
} else {
let failureReason = "String could not be serialized with encoding: \(actualEncoding)"
let error = Error.errorWithCode(.StringSerializationFailed, failureReason: failureReason)
return .Failure(data, error)
return .Failure(error)
}
}
}
......@@ -204,15 +220,13 @@ extension Request {
- parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the
server response, falling back to the default HTTP default character set,
ISO-8859-1.
- parameter completionHandler: A closure to be executed once the request has finished. The closure takes 3
arguments: the URL request, the URL response and the result produced while
creating the string.
- parameter completionHandler: A closure to be executed once the request has finished.
- returns: The request.
*/
public func responseString(
encoding encoding: NSStringEncoding? = nil,
completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<String>) -> Void)
completionHandler: Response<String, NSError> -> Void)
-> Self
{
return response(
......@@ -236,20 +250,22 @@ extension Request {
*/
public static func JSONResponseSerializer(
options options: NSJSONReadingOptions = .AllowFragments)
-> GenericResponseSerializer<AnyObject>
-> ResponseSerializer<AnyObject, NSError>
{
return GenericResponseSerializer { _, _, data in
guard let validData = data else {
let failureReason = "JSON could not be serialized because input data was nil."
return ResponseSerializer { _, _, data, error in
guard error == nil else { return .Failure(error!) }
guard let validData = data where validData.length > 0 else {
let failureReason = "JSON could not be serialized. Input data was nil or zero length."
let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
return .Failure(data, error)
return .Failure(error)
}
do {
let JSON = try NSJSONSerialization.JSONObjectWithData(validData, options: options)
return .Success(JSON)
} catch {
return .Failure(data, error as NSError)
return .Failure(error as NSError)
}
}
}
......@@ -258,15 +274,13 @@ extension Request {
Adds a handler to be called once the request has finished.
- parameter options: The JSON serialization reading options. `.AllowFragments` by default.
- parameter completionHandler: A closure to be executed once the request has finished. The closure takes 3
arguments: the URL request, the URL response and the result produced while
creating the JSON object.
- parameter completionHandler: A closure to be executed once the request has finished.
- returns: The request.
*/
public func responseJSON(
options options: NSJSONReadingOptions = .AllowFragments,
completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<AnyObject>) -> Void)
completionHandler: Response<AnyObject, NSError> -> Void)
-> Self
{
return response(
......@@ -290,20 +304,22 @@ extension Request {
*/
public static func propertyListResponseSerializer(
options options: NSPropertyListReadOptions = NSPropertyListReadOptions())
-> GenericResponseSerializer<AnyObject>
-> ResponseSerializer<AnyObject, NSError>
{
return GenericResponseSerializer { _, _, data in
guard let validData = data else {
let failureReason = "Property list could not be serialized because input data was nil."
return ResponseSerializer { _, _, data, error in
guard error == nil else { return .Failure(error!) }
guard let validData = data where validData.length > 0 else {
let failureReason = "Property list could not be serialized. Input data was nil or zero length."
let error = Error.errorWithCode(.PropertyListSerializationFailed, failureReason: failureReason)
return .Failure(data, error)
return .Failure(error)
}
do {
let plist = try NSPropertyListSerialization.propertyListWithData(validData, options: options, format: nil)
return .Success(plist)
} catch {
return .Failure(data, error as NSError)
return .Failure(error as NSError)
}
}
}
......@@ -313,14 +329,14 @@ extension Request {
- parameter options: The property list reading options. `0` by default.
- parameter completionHandler: A closure to be executed once the request has finished. The closure takes 3
arguments: the URL request, the URL response and the result produced while
creating the property list.
arguments: the URL request, the URL response, the server data and the result
produced while creating the property list.
- returns: The request.
*/
public func responsePropertyList(
options options: NSPropertyListReadOptions = NSPropertyListReadOptions(),
completionHandler: (NSURLRequest?, NSHTTPURLResponse?, Result<AnyObject>) -> Void)
completionHandler: Response<AnyObject, NSError> -> Void)
-> Self
{
return response(
......
......@@ -30,9 +30,9 @@ import Foundation
- Failure: The request encountered an error resulting in a failure. The associated values are the original data
provided by the server as well as the error that caused the failure.
*/
public enum Result<Value> {
public enum Result<Value, Error: ErrorType> {
case Success(Value)
case Failure(NSData?, ErrorType)
case Failure(Error)
/// Returns `true` if the result is a success, `false` otherwise.
public var isSuccess: Bool {
......@@ -59,22 +59,12 @@ public enum Result<Value> {
}
}
/// Returns the associated data value if the result is a failure, `nil` otherwise.
public var data: NSData? {
switch self {
case .Success:
return nil
case .Failure(let data, _):
return data
}
}
/// Returns the associated error value if the result is a failure, `nil` otherwise.
public var error: ErrorType? {
public var error: Error? {
switch self {
case .Success:
return nil
case .Failure(_, let error):
case .Failure(let error):
return error
}
}
......@@ -83,6 +73,8 @@ public enum Result<Value> {
// MARK: - CustomStringConvertible
extension Result: CustomStringConvertible {
/// The textual representation used when written to an output stream, which includes whether the result was a
/// success or failure.
public var description: String {
switch self {
case .Success:
......@@ -96,19 +88,14 @@ extension Result: CustomStringConvertible {
// MARK: - CustomDebugStringConvertible
extension Result: CustomDebugStringConvertible {
/// The debug textual representation used when written to an output stream, which includes whether the result was a
/// success or failure in addition to the value or error.
public var debugDescription: String {
switch self {
case .Success(let value):
return "SUCCESS: \(value)"
case .Failure(let data, let error):
if let
data = data,
utf8Data = NSString(data: data, encoding: NSUTF8StringEncoding)
{
return "FAILURE: \(error) \(utf8Data)"
} else {
return "FAILURE with Error: \(error)"
}
case .Failure(let error):
return "FAILURE: \(error)"
}
}
}
......@@ -32,7 +32,7 @@ extension Request {
*/
public enum ValidationResult {
case Success
case Failure(ErrorType)
case Failure(NSError)
}
/**
......
......@@ -57,7 +57,7 @@ class BasicAuthenticationTestCase: AuthenticationTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -79,7 +79,7 @@ class BasicAuthenticationTestCase: AuthenticationTestCase {
XCTAssertNotNil(data, "data should not be nil")
XCTAssertNotNil(error, "error should not be nil")
if let code = (error as? NSError)?.code {
if let code = error?.code {
XCTAssertEqual(code, -999, "error should be NSURLErrorDomain Code -999 'cancelled'")
}
}
......@@ -91,7 +91,7 @@ class BasicAuthenticationTestCase: AuthenticationTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -133,7 +133,7 @@ class HTTPDigestAuthenticationTestCase: AuthenticationTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -155,7 +155,7 @@ class HTTPDigestAuthenticationTestCase: AuthenticationTestCase {
XCTAssertNotNil(data, "data should not be nil")
XCTAssertNotNil(error, "error should not be nil")
if let code = (error as? NSError)?.code {
if let code = error?.code {
XCTAssertEqual(code, -999, "error should be NSURLErrorDomain Code -999 'cancelled'")
}
}
......@@ -167,7 +167,7 @@ class HTTPDigestAuthenticationTestCase: AuthenticationTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......
......@@ -94,7 +94,7 @@ class DownloadResponseTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var error: ErrorType?
var error: NSError?
// When
Alamofire.download(.GET, URLString, destination: destination)
......@@ -265,7 +265,7 @@ class DownloadResponseTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var error: ErrorType?
var error: NSError?
// When
Alamofire.download(.GET, URLString, parameters: parameters, destination: destination)
......@@ -307,7 +307,7 @@ class DownloadResponseTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var error: ErrorType?
var error: NSError?
// When
Alamofire.download(.GET, URLString, headers: headers, destination: destination)
......@@ -357,7 +357,7 @@ class DownloadResumeDataTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var error: ErrorType?
var error: NSError?
// When
let download = Alamofire.download(.GET, URLString, destination: destination)
......@@ -390,7 +390,7 @@ class DownloadResumeDataTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: AnyObject?
var error: ErrorType?
var error: NSError?
// When
let download = Alamofire.download(.GET, URLString, destination: destination)
......@@ -429,33 +429,30 @@ class DownloadResumeDataTestCase: BaseTestCase {
func testThatCancelledDownloadResumeDataIsAvailableWithJSONResponseSerializer() {
// Given
let expectation = expectationWithDescription("Download should be cancelled")
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var result: Result<AnyObject>!
var response: Response<AnyObject, NSError>?
// When
let download = Alamofire.download(.GET, URLString, destination: destination)
download.progress { _, _, _ in
download.cancel()
}
download.responseJSON { responseRequest, responseResponse, responseResult in
request = responseRequest
response = responseResponse
result = responseResult
download.responseJSON { closureResponse in
response = closureResponse
expectation.fulfill()
}
waitForExpectationsWithTimeout(defaultTimeout, handler: nil)
// Then
XCTAssertNotNil(request, "request should not be nil")
XCTAssertNotNil(response, "response should not be nil")
XCTAssertTrue(result.isFailure, "result should be a failure")
XCTAssertNotNil(result.data, "data should not be nil")
XCTAssertTrue(result.error != nil, "error should not be nil")
if let response = response {
XCTAssertNotNil(response.request, "request should not be nil")
XCTAssertNotNil(response.response, "response should not be nil")
XCTAssertNotNil(response.data, "data should not be nil")
XCTAssertTrue(response.result.isFailure, "result should be failure")
XCTAssertNotNil(response.result.error, "result error should not be nil")
} else {
XCTFail("response should not be nil")
}
XCTAssertNotNil(download.resumeData, "resume data should not be nil")
}
......
......@@ -20,11 +20,117 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Alamofire
@testable import Alamofire
import Foundation
import XCTest
class ManagerTestCase: BaseTestCase {
// MARK: Initialization Tests
func testInitializerWithDefaultArguments() {
// Given, When
let manager = Manager()
// Then
XCTAssertNotNil(manager.session.delegate, "session delegate should not be nil")
XCTAssertTrue(manager.delegate === manager.session.delegate, "manager delegate should equal session delegate")
XCTAssertNil(manager.session.serverTrustPolicyManager, "session server trust policy manager should be nil")
}
func testInitializerWithSpecifiedArguments() {
// Given
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let delegate = Manager.SessionDelegate()
let serverTrustPolicyManager = ServerTrustPolicyManager(policies: [:])
// When
let manager = Manager(
configuration: configuration,
delegate: delegate,
serverTrustPolicyManager: serverTrustPolicyManager
)
// Then
XCTAssertNotNil(manager.session.delegate, "session delegate should not be nil")
XCTAssertTrue(manager.delegate === manager.session.delegate, "manager delegate should equal session delegate")
XCTAssertNotNil(manager.session.serverTrustPolicyManager, "session server trust policy manager should not be nil")
}
func testThatFailableInitializerSucceedsWithDefaultArguments() {
// Given
let delegate = Manager.SessionDelegate()
let session: NSURLSession = {
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
return NSURLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
}()
// When
let manager = Manager(session: session, delegate: delegate)
// Then
if let manager = manager {
XCTAssertTrue(manager.delegate === manager.session.delegate, "manager delegate should equal session delegate")
XCTAssertNil(manager.session.serverTrustPolicyManager, "session server trust policy manager should be nil")
} else {
XCTFail("manager should not be nil")
}
}
func testThatFailableInitializerSucceedsWithSpecifiedArguments() {
// Given
let delegate = Manager.SessionDelegate()
let session: NSURLSession = {
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
return NSURLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
}()
let serverTrustPolicyManager = ServerTrustPolicyManager(policies: [:])
// When
let manager = Manager(session: session, delegate: delegate, serverTrustPolicyManager: serverTrustPolicyManager)
// Then
if let manager = manager {
XCTAssertTrue(manager.delegate === manager.session.delegate, "manager delegate should equal session delegate")
XCTAssertNotNil(manager.session.serverTrustPolicyManager, "session server trust policy manager should not be nil")
} else {
XCTFail("manager should not be nil")
}
}
func testThatFailableInitializerFailsWithWhenDelegateDoesNotEqualSessionDelegate() {
// Given
let delegate = Manager.SessionDelegate()
let session: NSURLSession = {
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
return NSURLSession(configuration: configuration, delegate: Manager.SessionDelegate(), delegateQueue: nil)
}()
// When
let manager = Manager(session: session, delegate: delegate)
// Then
XCTAssertNil(manager, "manager should be nil")
}
func testThatFailableInitializerFailsWhenSessionDelegateIsNil() {
// Given
let delegate = Manager.SessionDelegate()
let session: NSURLSession = {
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
return NSURLSession(configuration: configuration, delegate: nil, delegateQueue: nil)
}()
// When
let manager = Manager(session: session, delegate: delegate)
// Then
XCTAssertNil(manager, "manager should be nil")
}
// MARK: Start Requests Immediately Tests
func testSetStartRequestsImmediatelyToFalseAndResumeRequest() {
// Given
let manager = Alamofire.Manager()
......@@ -52,6 +158,8 @@ class ManagerTestCase: BaseTestCase {
XCTAssertTrue(response?.statusCode == 200, "response status code should be 200")
}
// MARK: Deinitialization Tests
func testReleasingManagerWithPendingRequestDeinitializesSuccessfully() {
// Given
var manager: Manager? = Alamofire.Manager()
......@@ -139,31 +247,26 @@ class ManagerConfigurationHeadersTestCase: BaseTestCase {
let expectation = expectationWithDescription("request should complete successfully")
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var result: Result<AnyObject>?
var response: Response<AnyObject, NSError>?
// When
manager.request(.GET, "https://httpbin.org/headers")
.responseJSON { responseRequest, responseResponse, responseResult in
request = responseRequest
response = responseResponse
result = responseResult
.responseJSON { closureResponse in
response = closureResponse
expectation.fulfill()
}
waitForExpectationsWithTimeout(defaultTimeout, handler: nil)
// Then
XCTAssertNotNil(request, "request should not be nil")
XCTAssertNotNil(response, "response should not be nil")
if let result = result {
XCTAssertTrue(result.isSuccess, "result should be a success")
if let response = response {
XCTAssertNotNil(response.request, "request should not be nil")
XCTAssertNotNil(response.response, "response should not be nil")
XCTAssertNotNil(response.data, "data should not be nil")
XCTAssertTrue(response.result.isSuccess, "result should be a success")
if let
headers = result.value?["headers" as NSString] as? [String: String],
headers = response.result.value?["headers" as NSString] as? [String: String],
authorization = headers["Authorization"]
{
XCTAssertEqual(authorization, "Bearer 123456", "authorization header value does not match")
......@@ -171,7 +274,7 @@ class ManagerConfigurationHeadersTestCase: BaseTestCase {
XCTFail("failed to extract authorization header value")
}
} else {
XCTFail("result should not be nil")
XCTFail("response should not be nil")
}
}
}
......@@ -31,8 +31,6 @@ class ParameterEncodingTestCase: BaseTestCase {
// MARK: -
class URLParameterEncodingTestCase: ParameterEncodingTestCase {
// MARK: Properties
let encoding: ParameterEncoding = .URL
// MARK: Tests - Parameter Types
......@@ -350,6 +348,23 @@ class URLParameterEncodingTestCase: ParameterEncodingTestCase {
XCTAssertEqual(URLRequest.URL?.query ?? "", "hd=%5B1%5D&%2Bfoo%2B=%2Bbar%2B", "query is incorrect")
}
func testURLParameterEncodeStringWithThousandsOfChineseCharacters() {
// Given
let repeatedCount = 2_000
let URL = NSURL(string: "https://example.com/movies")!
let parameters = ["chinese": String(count: repeatedCount, repeatedString: "一二三四五六七八九十")]
// When
let (URLRequest, _) = encoding.encode(NSURLRequest(URL: URL), parameters: parameters)
// Then
var expected = "chinese="
for _ in 0..<repeatedCount {
expected += "%E4%B8%80%E4%BA%8C%E4%B8%89%E5%9B%9B%E4%BA%94%E5%85%AD%E4%B8%83%E5%85%AB%E4%B9%9D%E5%8D%81"
}
XCTAssertEqual(URLRequest.URL?.query ?? "", expected, "query is incorrect")
}
// MARK: Tests - Varying HTTP Methods
func testThatURLParameterEncodingEncodesGETParametersInURL() {
......
......@@ -87,7 +87,7 @@ class RequestResponseTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString, parameters: ["foo": "bar"])
......@@ -290,37 +290,36 @@ class RequestResponseTestCase: BaseTestCase {
let expectation = expectationWithDescription("request should succeed")
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var result: Result<AnyObject>?
var response: Response<AnyObject, NSError>?
// When
Alamofire.request(.POST, URLString, parameters: parameters)
.responseJSON { responseRequest, responseResponse, responseResult in
request = responseRequest
response = responseResponse
result = responseResult
.responseJSON { closureResponse in
response = closureResponse
expectation.fulfill()
}
waitForExpectationsWithTimeout(defaultTimeout, handler: nil)
// Then
XCTAssertNotNil(request, "request should not be nil")
XCTAssertNotNil(response, "response should not be nil")
XCTAssertNotNil(result, "result should be nil")
if let
JSON = result?.value as? [String: AnyObject],
form = JSON["form"] as? [String: String]
{
XCTAssertEqual(form["french"], parameters["french"], "french parameter value should match form value")
XCTAssertEqual(form["japanese"], parameters["japanese"], "japanese parameter value should match form value")
XCTAssertEqual(form["arabic"], parameters["arabic"], "arabic parameter value should match form value")
XCTAssertEqual(form["emoji"], parameters["emoji"], "emoji parameter value should match form value")
if let response = response {
XCTAssertNotNil(response.request, "request should not be nil")
XCTAssertNotNil(response.response, "response should not be nil")
XCTAssertNotNil(response.data, "data should not be nil")
if let
JSON = response.result.value as? [String: AnyObject],
form = JSON["form"] as? [String: String]
{
XCTAssertEqual(form["french"], parameters["french"], "french parameter value should match form value")
XCTAssertEqual(form["japanese"], parameters["japanese"], "japanese parameter value should match form value")
XCTAssertEqual(form["arabic"], parameters["arabic"], "arabic parameter value should match form value")
XCTAssertEqual(form["emoji"], parameters["emoji"], "emoji parameter value should match form value")
} else {
XCTFail("form parameter in JSON should not be nil")
}
} else {
XCTFail("form parameter in JSON should not be nil")
XCTFail("response should not be nil")
}
}
......@@ -350,36 +349,36 @@ class RequestResponseTestCase: BaseTestCase {
let expectation = expectationWithDescription("request should succeed")
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var result: Result<AnyObject>?
var response: Response<AnyObject, NSError>?
// When
Alamofire.request(.POST, URLString, parameters: parameters)
.responseJSON { responseRequest, responseResponse, responseResult in
request = responseRequest
response = responseResponse
result = responseResult
.responseJSON { closureResponse in
response = closureResponse
expectation.fulfill()
}
}
waitForExpectationsWithTimeout(defaultTimeout, handler: nil)
// Then
XCTAssertNotNil(request, "request should not be nil")
XCTAssertNotNil(response, "response should not be nil")
XCTAssertNotNil(result, "result should be nil")
if let
JSON = result?.value as? [String: AnyObject],
form = JSON["form"] as? [String: String]
{
XCTAssertEqual(form["email"], parameters["email"], "email parameter value should match form value")
XCTAssertEqual(form["png_image"], parameters["png_image"], "png_image parameter value should match form value")
XCTAssertEqual(form["jpeg_image"], parameters["jpeg_image"], "jpeg_image parameter value should match form value")
if let response = response {
XCTAssertNotNil(response.request, "request should not be nil")
XCTAssertNotNil(response.response, "response should not be nil")
XCTAssertNotNil(response.data, "data should not be nil")
XCTAssertTrue(response.result.isSuccess, "result should be success")
if let
JSON = response.result.value as? [String: AnyObject],
form = JSON["form"] as? [String: String]
{
XCTAssertEqual(form["email"], parameters["email"], "email parameter value should match form value")
XCTAssertEqual(form["png_image"], parameters["png_image"], "png_image parameter value should match form value")
XCTAssertEqual(form["jpeg_image"], parameters["jpeg_image"], "jpeg_image parameter value should match form value")
} else {
XCTFail("form parameter in JSON should not be nil")
}
} else {
XCTFail("form parameter in JSON should not be nil")
XCTFail("response should not be nil")
}
}
}
......
此差异已折叠。
......@@ -30,18 +30,16 @@ class ResultTestCase: BaseTestCase {
// MARK: - Is Success Tests
func testThatIsSuccessPropertyReturnsTrueForSuccessCase() {
// Given
// When
let result = Result.Success("success")
// Given, When
let result = Result<String, NSError>.Success("success")
// Then
XCTAssertTrue(result.isSuccess, "result is success should be true for success case")
}
func testThatIsSuccessPropertyReturnsFalseForFailureCase() {
// Given
// When
let result = Result<String>.Failure(NSData(), error)
// Given, When
let result = Result<String, NSError>.Failure(error)
// Then
XCTAssertFalse(result.isSuccess, "result is success should be true for failure case")
......@@ -50,18 +48,16 @@ class ResultTestCase: BaseTestCase {
// MARK: - Is Failure Tests
func testThatIsFailurePropertyReturnsFalseForSuccessCase() {
// Given
// When
let result = Result.Success("success")
// Given, When
let result = Result<String, NSError>.Success("success")
// Then
XCTAssertFalse(result.isFailure, "result is failure should be false for success case")
}
func testThatIsFailurePropertyReturnsTrueForFailureCase() {
// Given
// When
let result = Result<String>.Failure(NSData(), error)
// Given, When
let result = Result<String, NSError>.Failure(error)
// Then
XCTAssertTrue(result.isFailure, "result is failure should be true for failure case")
......@@ -70,60 +66,34 @@ class ResultTestCase: BaseTestCase {
// MARK: - Value Tests
func testThatValuePropertyReturnsValueForSuccessCase() {
// Given
// When
let result = Result.Success("success")
// Given, When
let result = Result<String, NSError>.Success("success")
// Then
XCTAssertEqual(result.value ?? "", "success", "result value should match expected value")
}
func testThatValuePropertyReturnsNilForFailureCase() {
// Given
// When
let result = Result<String>.Failure(NSData(), error)
// Given, When
let result = Result<String, NSError>.Failure(error)
// Then
XCTAssertNil(result.value, "result value should be nil for failure case")
}
// MARK: - Data Tests
func testThatDataPropertyReturnsNilForSuccessCase() {
// Given
// When
let result = Result.Success("success")
// Then
XCTAssertNil(result.data, "result data should be nil for success case")
}
func testThatDataPropertyReturnsDataForFailureCase() {
// Given
// When
let resultWithData = Result<String>.Failure(NSData(), error)
let resultWithoutData = Result<String>.Failure(nil, error)
// Then
XCTAssertNotNil(resultWithData.data, "result with data should not be nil for failure case")
XCTAssertNil(resultWithoutData.data, "result without data should be nil for failure case")
}
// MARK: - Error Tests
func testThatErrorPropertyReturnsNilForSuccessCase() {
// Given
// When
let result = Result.Success("success")
// Given, When
let result = Result<String, NSError>.Success("success")
// Then
XCTAssertTrue(result.error == nil, "result error should be nil for success case")
}
func testThatErrorPropertyReturnsErrorForFailureCase() {
// Given
// When
let result = Result<String>.Failure(nil, error)
// Given, When
let result = Result<String, NSError>.Failure(error)
// Then
XCTAssertTrue(result.error != nil, "result error should not be nil for failure case")
......@@ -132,18 +102,16 @@ class ResultTestCase: BaseTestCase {
// MARK: - Description Tests
func testThatDescriptionStringMatchesExpectedValueForSuccessCase() {
// Given
// When
let result = Result.Success("success")
// Given, When
let result = Result<String, NSError>.Success("success")
// Then
XCTAssertEqual(result.description, "SUCCESS", "result description should match expected value for success case")
}
func testThatDescriptionStringMatchesExpectedValueForFailureCase() {
// Given
// When
let result = Result<String>.Failure(nil, error)
// Given, When
let result = Result<String, NSError>.Failure(error)
// Then
XCTAssertEqual(result.description, "FAILURE", "result description should match expected value for failure case")
......@@ -152,9 +120,8 @@ class ResultTestCase: BaseTestCase {
// MARK: - Debug Description Tests
func testThatDebugDescriptionStringMatchesExpectedValueForSuccessCase() {
// Given
// When
let result = Result.Success("success value")
// Given, When
let result = Result<String, NSError>.Success("success value")
// Then
XCTAssertEqual(
......@@ -165,29 +132,13 @@ class ResultTestCase: BaseTestCase {
}
func testThatDebugDescriptionStringMatchesExpectedValueForFailureCase() {
// Given
let utf8Data = "failure value".dataUsingEncoding(NSUTF8StringEncoding)!
let imageData = NSData(contentsOfURL: URLForResource("rainbow", withExtension: "jpg"))!
// When
let resultWithUTF8Data = Result<String>.Failure(utf8Data, error)
let resultWithImageData = Result<String>.Failure(imageData, error)
let resultWithNoData = Result<String>.Failure(nil, error)
// Given, When
let result = Result<String, NSError>.Failure(error)
// Then
XCTAssertEqual(
resultWithUTF8Data.debugDescription,
"FAILURE: \(error) failure value",
"result debug description should match expected value for failure case"
)
XCTAssertEqual(
resultWithImageData.debugDescription,
"FAILURE with Error: \(error)",
"result debug description should match expected value for failure case"
)
XCTAssertEqual(
resultWithNoData.debugDescription,
"FAILURE with Error: \(error)",
result.debugDescription,
"FAILURE: \(error)",
"result debug description should match expected value for failure case"
)
}
......
// NSURLSessionConfiguration+AlamofireTests.swift
//
// Copyright (c) 2014–2015 Alamofire Software Foundation (http://alamofire.org/)
//
// 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 the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
extension String {
init(count: Int, repeatedString: String) {
var value = ""
for _ in 0..<count { value += repeatedString }
self = value
}
}
......@@ -77,7 +77,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
// Given
let expectation = expectationWithDescription("\(URL)")
let manager = Manager(configuration: configuration)
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -91,7 +91,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let code = (error as? NSError)?.code {
if let code = error?.code {
XCTAssertEqual(code, NSURLErrorServerCertificateUntrusted, "code should be untrusted server certficate")
} else {
XCTFail("error should be an NSError")
......@@ -109,7 +109,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -123,7 +123,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let code = (error as? NSError)?.code {
if let code = error?.code {
XCTAssertEqual(code, NSURLErrorCancelled, "code should be cancelled")
} else {
XCTFail("error should be an NSError")
......@@ -145,7 +145,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -159,7 +159,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let code = (error as? NSError)?.code {
if let code = error?.code {
XCTAssertEqual(code, NSURLErrorCancelled, "code should be cancelled")
} else {
XCTFail("error should be an NSError")
......@@ -179,7 +179,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -193,7 +193,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let code = (error as? NSError)?.code {
if let code = error?.code {
XCTAssertEqual(code, NSURLErrorCancelled, "code should be cancelled")
} else {
XCTFail("error should be an NSError")
......@@ -213,7 +213,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -241,7 +241,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -269,7 +269,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -299,7 +299,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -313,7 +313,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let code = (error as? NSError)?.code {
if let code = error?.code {
XCTAssertEqual(code, NSURLErrorCancelled, "code should be cancelled")
} else {
XCTFail("error should be an NSError")
......@@ -333,7 +333,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -361,7 +361,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -389,7 +389,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -415,7 +415,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -447,7 +447,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -477,7 +477,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
)
let expectation = expectationWithDescription("\(URL)")
var error: ErrorType?
var error: NSError?
// When
manager.request(.GET, URL)
......@@ -491,7 +491,7 @@ class TLSEvaluationExpiredLeafCertificateTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let code = (error as? NSError)?.code {
if let code = error?.code {
XCTAssertEqual(code, NSURLErrorCancelled, "code should be cancelled")
} else {
XCTFail("error should be an NSError")
......
......@@ -138,7 +138,7 @@ class URLProtocolTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(URLRequest)
......
......@@ -148,7 +148,7 @@ class UploadDataTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var error: ErrorType?
var error: NSError?
// When
Alamofire.upload(.POST, URLString, data: data)
......@@ -275,7 +275,7 @@ class UploadMultipartFormDataTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
// When
Alamofire.upload(
......@@ -332,7 +332,7 @@ class UploadMultipartFormDataTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
// When
Alamofire.upload(
......@@ -601,7 +601,7 @@ class UploadMultipartFormDataTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
var streamingFromDisk: Bool?
// When
......@@ -675,7 +675,7 @@ class UploadMultipartFormDataTestCase: BaseTestCase {
var request: NSURLRequest?
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
// When
Alamofire.upload(
......
......@@ -30,7 +30,7 @@ class StatusCodeValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/status/200"
let expectation = expectationWithDescription("request should return 200 status code")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -51,7 +51,7 @@ class StatusCodeValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/status/404"
let expectation = expectationWithDescription("request should return 404 status code")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -66,7 +66,7 @@ class StatusCodeValidationTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let error = error as? NSError {
if let error = error {
XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain")
XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue, "code should be status code validation failure")
} else {
......@@ -79,7 +79,7 @@ class StatusCodeValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/status/201"
let expectation = expectationWithDescription("request should return 201 status code")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -94,7 +94,7 @@ class StatusCodeValidationTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let error = error as? NSError {
if let error = error {
XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain")
XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue, "code should be status code validation failure")
} else {
......@@ -111,7 +111,7 @@ class ContentTypeValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/ip"
let expectation = expectationWithDescription("request should succeed and return ip")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -132,7 +132,7 @@ class ContentTypeValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/ip"
let expectation = expectationWithDescription("request should succeed and return ip")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -155,7 +155,7 @@ class ContentTypeValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/xml"
let expectation = expectationWithDescription("request should succeed and return xml")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -170,7 +170,7 @@ class ContentTypeValidationTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let error = error as? NSError {
if let error = error {
XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain")
XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue, "code should be content type validation failure")
} else {
......@@ -183,7 +183,7 @@ class ContentTypeValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/xml"
let expectation = expectationWithDescription("request should succeed and return xml")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -198,7 +198,7 @@ class ContentTypeValidationTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let error = error as? NSError {
if let error = error {
XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain")
XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue, "code should be content type validation failure")
} else {
......@@ -258,7 +258,7 @@ class ContentTypeValidationTestCase: BaseTestCase {
var response: NSHTTPURLResponse?
var data: NSData?
var error: ErrorType?
var error: NSError?
// When
manager.request(.DELETE, URLString)
......@@ -293,7 +293,7 @@ class MultipleValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/ip"
let expectation = expectationWithDescription("request should succeed and return ip")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -315,7 +315,7 @@ class MultipleValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/xml"
let expectation = expectationWithDescription("request should succeed and return xml")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -331,7 +331,7 @@ class MultipleValidationTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let error = error as? NSError {
if let error = error {
XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain")
XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue, "code should be status code validation failure")
} else {
......@@ -344,7 +344,7 @@ class MultipleValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/xml"
let expectation = expectationWithDescription("request should succeed and return xml")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -360,7 +360,7 @@ class MultipleValidationTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let error = error as? NSError {
if let error = error {
XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain")
XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue, "code should be content type validation failure")
} else {
......@@ -380,7 +380,7 @@ class AutomaticValidationTestCase: BaseTestCase {
let expectation = expectationWithDescription("request should succeed and return ip")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(mutableURLRequest)
......@@ -401,7 +401,7 @@ class AutomaticValidationTestCase: BaseTestCase {
let URLString = "https://httpbin.org/status/404"
let expectation = expectationWithDescription("request should return 404 status code")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(.GET, URLString)
......@@ -416,7 +416,7 @@ class AutomaticValidationTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let error = error as? NSError {
if let error = error {
XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain")
XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue, "code should be status code validation failure")
} else {
......@@ -432,7 +432,7 @@ class AutomaticValidationTestCase: BaseTestCase {
let expectation = expectationWithDescription("request should succeed and return ip")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(mutableURLRequest)
......@@ -458,7 +458,7 @@ class AutomaticValidationTestCase: BaseTestCase {
let expectation = expectationWithDescription("request should succeed and return xml")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(mutableURLRequest)
......@@ -482,7 +482,7 @@ class AutomaticValidationTestCase: BaseTestCase {
let expectation = expectationWithDescription("request should succeed and return xml")
var error: ErrorType?
var error: NSError?
// When
Alamofire.request(mutableURLRequest)
......@@ -497,7 +497,7 @@ class AutomaticValidationTestCase: BaseTestCase {
// Then
XCTAssertNotNil(error, "error should not be nil")
if let error = error as? NSError {
if let error = error {
XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain")
XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue, "code should be content type validation failure")
} else {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册