Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
white49
Alamofire
提交
2154c666
A
Alamofire
项目概览
white49
/
Alamofire
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
Alamofire
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
2154c666
编写于
4月 23, 2019
作者:
C
Christian Noon
提交者:
Jon Shier
4月 23, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Fixed issue where serializer completion was not called when request was complete (#2810)
上级
9bade216
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
126 addition
and
22 deletion
+126
-22
Source/AFError.swift
Source/AFError.swift
+4
-0
Source/Request.swift
Source/Request.swift
+38
-11
Source/Session.swift
Source/Session.swift
+3
-0
Tests/AFError+AlamofireTests.swift
Tests/AFError+AlamofireTests.swift
+10
-0
Tests/DownloadTests.swift
Tests/DownloadTests.swift
+1
-1
Tests/RequestTests.swift
Tests/RequestTests.swift
+68
-8
Tests/SessionTests.swift
Tests/SessionTests.swift
+1
-1
Tests/UploadTests.swift
Tests/UploadTests.swift
+1
-1
未找到文件。
Source/AFError.swift
浏览文件 @
2154c666
...
...
@@ -139,6 +139,8 @@ public enum AFError: Error {
case
decodingFailed
(
error
:
Error
)
/// Generic serialization failed for an empty response that wasn't type `Empty` but instead the associated type.
case
invalidEmptyResponse
(
type
:
String
)
/// A response serializer was added to the request after the request was already finished.
case
responseSerializerAddedAfterRequestFinished
}
/// Underlying reason a server trust evaluation error occured.
...
...
@@ -554,6 +556,8 @@ extension AFError.ResponseSerializationFailureReason {
return
"Empty response could not be serialized to type:
\(
type
)
. Use Empty as the expected type for such responses."
case
.
decodingFailed
(
let
error
):
return
"Response could not be decoded because of error:
\n\(
error
.
localizedDescription
)
"
case
.
responseSerializerAddedAfterRequestFinished
:
return
"Response serializer was added to the request after it had already finished."
}
}
}
...
...
Source/Request.swift
浏览文件 @
2154c666
...
...
@@ -38,17 +38,24 @@ public class Request {
/// - cancelled: Set when `cancel()` is called. Any tasks created for the `Request` will have `cancel()` called on
/// them. Unlike `resumed` or `suspended`, once in the `cancelled` state, the `Request` can no longer
/// transition to any other state.
/// - finished: Set when all response serialization completion closures have been cleared on the `Request` and
/// queued on their respective queues.
public
enum
State
{
case
initialized
,
resumed
,
suspended
,
cancelled
case
initialized
,
resumed
,
suspended
,
cancelled
,
finished
/// Determines whether `self` can be transitioned to `state`.
func
canTransitionTo
(
_
state
:
State
)
->
Bool
{
switch
(
self
,
state
)
{
case
(
.
initialized
,
_
):
return
true
case
(
_
,
.
initialized
),
(
.
cancelled
,
_
):
return
false
case
(
.
resumed
,
.
cancelled
),
(
.
suspended
,
.
cancelled
),
(
.
resumed
,
.
suspended
),
(
.
suspended
,
.
resumed
):
return
true
case
(
.
suspended
,
.
suspended
),
(
.
resumed
,
.
resumed
):
return
false
case
(
.
initialized
,
_
):
return
true
case
(
_
,
.
initialized
),
(
.
cancelled
,
_
),
(
.
finished
,
_
):
return
false
case
(
.
resumed
,
.
cancelled
),
(
.
suspended
,
.
cancelled
),
(
.
resumed
,
.
suspended
),
(
.
suspended
,
.
resumed
):
return
true
case
(
.
suspended
,
.
suspended
),
(
.
resumed
,
.
resumed
):
return
false
case
(
_
,
.
finished
):
return
true
}
}
}
...
...
@@ -86,6 +93,8 @@ public class Request {
var
responseSerializers
:
[()
->
Void
]
=
[]
/// Response serialization completion closures executed once all response serialization is complete.
var
responseSerializerCompletions
:
[()
->
Void
]
=
[]
/// Whether response serializer processing is finished.
var
responseSerializerProcessingFinished
=
false
/// `URLCredential` used for authentication challenges.
var
credential
:
URLCredential
?
/// All `URLRequest`s created by Alamofire on behalf of the `Request`.
...
...
@@ -106,14 +115,16 @@ public class Request {
/// `State` of the `Request`.
public
var
state
:
State
{
return
protectedMutableState
.
directValue
.
state
}
/// Returns whether `state` is `.
cancell
ed`.
public
var
is
Cancelled
:
Bool
{
return
state
==
.
cancell
ed
}
/// Returns whether `state` is `.
initializ
ed`.
public
var
is
Initialized
:
Bool
{
return
state
==
.
initializ
ed
}
/// Returns whether `state is `.resumed`.
public
var
isResumed
:
Bool
{
return
state
==
.
resumed
}
/// Returns whether `state` is `.suspended`.
public
var
isSuspended
:
Bool
{
return
state
==
.
suspended
}
/// Returns whether `state` is `.initialized`.
public
var
isInitialized
:
Bool
{
return
state
==
.
initialized
}
/// Returns whether `state` is `.cancelled`.
public
var
isCancelled
:
Bool
{
return
state
==
.
cancelled
}
/// Returns whether `state` is `.finished`.
public
var
isFinished
:
Bool
{
return
state
==
.
finished
}
// Progress
...
...
@@ -387,7 +398,17 @@ public class Request {
/// Appends the response serialization closure to the `Request`.
func
appendResponseSerializer
(
_
closure
:
@escaping
()
->
Void
)
{
protectedMutableState
.
write
{
$0
.
responseSerializers
.
append
(
closure
)
}
protectedMutableState
.
write
{
mutableState
in
mutableState
.
responseSerializers
.
append
(
closure
)
if
mutableState
.
state
==
.
finished
{
mutableState
.
error
=
AFError
.
responseSerializationFailed
(
reason
:
.
responseSerializerAddedAfterRequestFinished
)
}
if
mutableState
.
responseSerializerProcessingFinished
{
underlyingQueue
.
async
{
self
.
processNextResponseSerializer
()
}
}
}
}
/// Returns the next response serializer closure to execute if there's one left.
...
...
@@ -420,6 +441,12 @@ public class Request {
// An example of how this can happen is by calling cancel inside a response completion closure.
mutableState
.
responseSerializers
.
removeAll
()
mutableState
.
responseSerializerCompletions
.
removeAll
()
if
mutableState
.
state
.
canTransitionTo
(
.
finished
)
{
mutableState
.
state
=
.
finished
}
mutableState
.
responseSerializerProcessingFinished
=
true
}
completions
.
forEach
{
$0
()
}
...
...
Source/Session.swift
浏览文件 @
2154c666
...
...
@@ -485,6 +485,9 @@ open class Session {
case
(
_
,
.
cancelled
):
task
.
cancel
()
rootQueue
.
async
{
request
.
didCancelTask
(
task
)
}
case
(
_
,
.
finished
):
// Do nothing
break
}
}
}
...
...
Tests/AFError+AlamofireTests.swift
浏览文件 @
2154c666
...
...
@@ -142,6 +142,11 @@ extension AFError {
return
false
}
var
isResponseSerializerAddedAfterRequestFinished
:
Bool
{
if
case
let
.
responseSerializationFailed
(
reason
)
=
self
,
reason
.
isResponseSerializerAddedAfterRequestFinished
{
return
true
}
return
false
}
// ResponseValidationFailureReason
var
isDataFileNil
:
Bool
{
...
...
@@ -290,6 +295,11 @@ extension AFError.ResponseSerializationFailureReason {
if
case
.
invalidEmptyResponse
=
self
{
return
true
}
return
false
}
var
isResponseSerializerAddedAfterRequestFinished
:
Bool
{
if
case
.
responseSerializerAddedAfterRequestFinished
=
self
{
return
true
}
return
false
}
}
// MARK: -
...
...
Tests/DownloadTests.swift
浏览文件 @
2154c666
...
...
@@ -419,7 +419,7 @@ final class DownloadRequestEventsTestCase: BaseTestCase {
waitForExpectations
(
timeout
:
timeout
,
handler
:
nil
)
// Then
XCTAssertEqual
(
request
.
state
,
.
resum
ed
)
XCTAssertEqual
(
request
.
state
,
.
finish
ed
)
}
func
testThatCancelledDownloadRequestTriggersAllAppropriateLifetimeEvents
()
{
...
...
Tests/RequestTests.swift
浏览文件 @
2154c666
...
...
@@ -26,8 +26,6 @@ import Alamofire
import
Foundation
import
XCTest
// MARK: -
class
RequestResponseTestCase
:
BaseTestCase
{
func
testRequestResponse
()
{
// Given
...
...
@@ -263,7 +261,7 @@ class RequestResponseTestCase: BaseTestCase {
XCTAssertEqual
(
receivedResponse
?
.
result
.
value
?
.
form
,
[
"property"
:
"one"
])
}
// MARK:
-
Lifetime Events
// MARK: Lifetime Events
func
testThatAutomaticallyResumedRequestReceivesAppropriateLifetimeEvents
()
{
// Given
...
...
@@ -288,7 +286,7 @@ class RequestResponseTestCase: BaseTestCase {
waitForExpectations
(
timeout
:
timeout
,
handler
:
nil
)
// Then
XCTAssertEqual
(
request
.
state
,
.
resum
ed
)
XCTAssertEqual
(
request
.
state
,
.
finish
ed
)
}
func
testThatAutomaticallyAndManuallyResumedRequestReceivesAppropriateLifetimeEvents
()
{
...
...
@@ -317,7 +315,7 @@ class RequestResponseTestCase: BaseTestCase {
waitForExpectations
(
timeout
:
timeout
,
handler
:
nil
)
// Then
XCTAssertEqual
(
request
.
state
,
.
resum
ed
)
XCTAssertEqual
(
request
.
state
,
.
finish
ed
)
}
func
testThatManuallyResumedRequestReceivesAppropriateLifetimeEvents
()
{
...
...
@@ -346,7 +344,7 @@ class RequestResponseTestCase: BaseTestCase {
waitForExpectations
(
timeout
:
timeout
,
handler
:
nil
)
// Then
XCTAssertEqual
(
request
.
state
,
.
resum
ed
)
XCTAssertEqual
(
request
.
state
,
.
finish
ed
)
}
func
testThatRequestManuallyResumedManyTimesOnlyReceivesAppropriateLifetimeEvents
()
{
...
...
@@ -375,7 +373,7 @@ class RequestResponseTestCase: BaseTestCase {
waitForExpectations
(
timeout
:
timeout
,
handler
:
nil
)
// Then
XCTAssertEqual
(
request
.
state
,
.
resum
ed
)
XCTAssertEqual
(
request
.
state
,
.
finish
ed
)
}
func
testThatRequestManuallySuspendedManyTimesAfterAutomaticResumeOnlyReceivesAppropriateLifetimeEvents
()
{
...
...
@@ -561,7 +559,7 @@ class RequestResponseTestCase: BaseTestCase {
waitForExpectations
(
timeout
:
timeout
,
handler
:
nil
)
// Then
XCTAssertEqual
(
request
.
state
,
.
resum
ed
)
XCTAssertEqual
(
request
.
state
,
.
finish
ed
)
}
func
testThatCancelledRequestTriggersAllAppropriateLifetimeEvents
()
{
...
...
@@ -600,6 +598,68 @@ class RequestResponseTestCase: BaseTestCase {
// Then
XCTAssertEqual
(
request
.
state
,
.
cancelled
)
}
func
testThatAppendingResponseSerializerToCancelledRequestCallsCompletion
()
{
// Given
let
session
=
Session
()
var
response1
:
DataResponse
<
Any
>
?
var
response2
:
DataResponse
<
Any
>
?
let
expect
=
expectation
(
description
:
"both response serializer completions should be called"
)
expect
.
expectedFulfillmentCount
=
2
// When
let
request
=
session
.
request
(
URLRequest
.
makeHTTPBinRequest
())
request
.
responseJSON
{
resp
in
response1
=
resp
expect
.
fulfill
()
request
.
responseJSON
{
resp
in
response2
=
resp
expect
.
fulfill
()
}
}
request
.
cancel
()
waitForExpectations
(
timeout
:
timeout
,
handler
:
nil
)
// Then
XCTAssertEqual
(
response1
?
.
error
?
.
asAFError
?
.
isExplicitlyCancelledError
,
true
)
XCTAssertEqual
(
response2
?
.
error
?
.
asAFError
?
.
isExplicitlyCancelledError
,
true
)
}
func
testThatAppendingResponseSerializerToCompletedRequestCallsCompletion
()
{
// Given
let
session
=
Session
()
var
response1
:
DataResponse
<
Any
>
?
var
response2
:
DataResponse
<
Any
>
?
let
expect
=
expectation
(
description
:
"both response serializer completions should be called"
)
expect
.
expectedFulfillmentCount
=
2
// When
let
request
=
session
.
request
(
URLRequest
.
makeHTTPBinRequest
())
request
.
responseJSON
{
resp
in
response1
=
resp
expect
.
fulfill
()
request
.
responseJSON
{
resp
in
response2
=
resp
expect
.
fulfill
()
}
}
waitForExpectations
(
timeout
:
timeout
,
handler
:
nil
)
// Then
XCTAssertNotNil
(
response1
?
.
value
)
XCTAssertEqual
(
response2
?
.
error
?
.
asAFError
?
.
isResponseSerializerAddedAfterRequestFinished
,
true
)
}
}
// MARK: -
...
...
Tests/SessionTests.swift
浏览文件 @
2154c666
...
...
@@ -1491,7 +1491,7 @@ class SessionTestCase: BaseTestCase {
waitForExpectations
(
timeout
:
timeout
,
handler
:
nil
)
// Then
XCTAssertEqual
(
request
.
state
,
.
resum
ed
)
XCTAssertEqual
(
request
.
state
,
.
finish
ed
)
XCTAssertEqual
(
response
?
.
result
.
isSuccess
,
true
)
}
}
...
...
Tests/UploadTests.swift
浏览文件 @
2154c666
...
...
@@ -678,7 +678,7 @@ final class UploadRequestEventsTestCase: BaseTestCase {
waitForExpectations
(
timeout
:
timeout
,
handler
:
nil
)
// Then
XCTAssertEqual
(
request
.
state
,
.
resum
ed
)
XCTAssertEqual
(
request
.
state
,
.
finish
ed
)
}
func
testThatCancelledUploadRequestTriggersAllAppropriateLifetimeEvents
()
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录