mirror of
https://github.com/Moya/Moya.git
synced 2026-03-18 19:52:28 +00:00
Merge branch 'development' into development-swift-5.1
This commit is contained in:
@@ -0,0 +1 @@
|
||||
github: [sunshinejr]
|
||||
@@ -1,3 +1,3 @@
|
||||
github "Alamofire/Alamofire" "5.0.0-rc.2"
|
||||
github "Alamofire/Alamofire" "5.0.0-rc.3"
|
||||
github "ReactiveCocoa/ReactiveSwift" ~> 6.0
|
||||
github "ReactiveX/RxSwift" ~> 5.0
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
github "Alamofire/Alamofire" "5.0.0-rc.2"
|
||||
github "Alamofire/Alamofire" "5.0.0-rc.3"
|
||||
github "AliSoftware/OHHTTPStubs" "8.0.0"
|
||||
github "Quick/Nimble" "v8.0.4"
|
||||
github "Quick/Quick" "v2.2.0"
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
|
||||
### Changed
|
||||
- Moya's Swift version is now Swift 5.1. [#1931](https://github.com/Moya/Moya/pull/1931) by [@BasThomas](https://github.com/BasThomas).
|
||||
# [14.0.0-beta.5] - 2019-10-27
|
||||
|
||||
### Changed
|
||||
- **Breaking Change** Minimum version of `Alamofire` is now 5.0.0-rc.3. [#1944](https://github.com/Moya/Moya/pull/1944) by [@sunshinejr](https://github.com/sunshinejr).
|
||||
|
||||
# [14.0.0-beta.4] - 2019-10-05
|
||||
|
||||
### Removed
|
||||
- **Breaking Change** Removed Combine extensions for now. Due to problems with weak-linking the framework, it's too difficult to support it with ease using all package managers and also without breaking backwards-compatibility. Probably gonna introduce it once we only support Xcode 11. [#1933](https://github.com/Moya/Moya/pull/1933) by [@sunshinejr](https://github.com/sunshinejr)
|
||||
|
||||
# [14.0.0-beta.3] - 2019-09-27
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import UIKit
|
||||
import Moya
|
||||
import Combine
|
||||
|
||||
class ViewController: UITableViewController {
|
||||
var progressView = UIView()
|
||||
var repos = NSArray()
|
||||
var cancellable: AnyCancellable?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
@@ -41,11 +39,16 @@ class ViewController: UITableViewController {
|
||||
}
|
||||
|
||||
func downloadZen() {
|
||||
cancellable = gitHubProvider.requestPublisher(.zen)
|
||||
.mapString()
|
||||
.sink(receiveCompletion: { _ in }, receiveValue: { message in
|
||||
self.showAlert("Zen", message: message)
|
||||
})
|
||||
gitHubProvider.request(.zen) { result in
|
||||
var message = "Couldn't access API"
|
||||
|
||||
if case let .success(response) = result {
|
||||
let jsonString = try? response.mapString()
|
||||
message = jsonString ?? message
|
||||
}
|
||||
|
||||
self.showAlert("Zen", message: message)
|
||||
}
|
||||
}
|
||||
|
||||
func uploadGiphy() {
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "Moya"
|
||||
s.version = "14.0.0-beta.3"
|
||||
s.version = "14.0.0-beta.5"
|
||||
s.summary = "Network abstraction layer written in Swift"
|
||||
s.description = <<-EOS
|
||||
Moya abstracts network commands using Swift Generics to provide developers
|
||||
@@ -23,8 +23,8 @@ Pod::Spec.new do |s|
|
||||
s.cocoapods_version = '>= 1.4.0'
|
||||
|
||||
s.subspec "Core" do |ss|
|
||||
ss.source_files = "Sources/Moya/", "Sources/Moya/Combine", "Sources/Moya/Plugins/"
|
||||
ss.dependency "Alamofire", "5.0.0-rc.2"
|
||||
ss.source_files = "Sources/Moya/", "Sources/Moya/Plugins/"
|
||||
ss.dependency "Alamofire", "5.0.0-rc.3"
|
||||
ss.framework = "Foundation"
|
||||
end
|
||||
|
||||
|
||||
@@ -63,10 +63,6 @@
|
||||
83B0E400A7562256224CB7FF /* AccessTokenPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC115388D44D0DB7A753E9BB /* AccessTokenPlugin.swift */; };
|
||||
85850A4122CF5AB50089E731 /* NimbleHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85850A4022CF5AB50089E731 /* NimbleHelpers.swift */; };
|
||||
85B2DBBC221C69620098F59A /* PropertyListEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85B2DBBB221C69620098F59A /* PropertyListEncoding.swift */; };
|
||||
85C98000231D2D4000AAAFB2 /* MoyaProvider+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85C97FFF231D2D4000AAAFB2 /* MoyaProvider+Combine.swift */; };
|
||||
85C98002231D3EC700AAAFB2 /* MoyaProvider+CombineSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85C98001231D3EC700AAAFB2 /* MoyaProvider+CombineSpec.swift */; };
|
||||
85C98006231D41E400AAAFB2 /* MoyaPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85C98005231D41E400AAAFB2 /* MoyaPublisher.swift */; };
|
||||
85C98008231D4BE900AAAFB2 /* AnyPublisher+Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85C98007231D4BE900AAAFB2 /* AnyPublisher+Response.swift */; };
|
||||
85D5277A2302BEF30093E9C1 /* TestImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85D527792302BEF30093E9C1 /* TestImage.swift */; };
|
||||
85F6042E22A018BB00063320 /* RequestTypeWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 85F6042D22A018BB00063320 /* RequestTypeWrapper.swift */; };
|
||||
8995DF740A59721AA79F5B43 /* MoyaProvider+ReactiveSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = C841AA621AEC61FAEA0CA019 /* MoyaProvider+ReactiveSpec.swift */; };
|
||||
@@ -197,10 +193,6 @@
|
||||
851FFE6DC58E873408D0E8E7 /* MoyaProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = MoyaProvider.swift; sourceTree = "<group>"; };
|
||||
85850A4022CF5AB50089E731 /* NimbleHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NimbleHelpers.swift; sourceTree = "<group>"; };
|
||||
85B2DBBB221C69620098F59A /* PropertyListEncoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyListEncoding.swift; sourceTree = "<group>"; };
|
||||
85C97FFF231D2D4000AAAFB2 /* MoyaProvider+Combine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MoyaProvider+Combine.swift"; sourceTree = "<group>"; };
|
||||
85C98001231D3EC700AAAFB2 /* MoyaProvider+CombineSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MoyaProvider+CombineSpec.swift"; sourceTree = "<group>"; };
|
||||
85C98005231D41E400AAAFB2 /* MoyaPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoyaPublisher.swift; sourceTree = "<group>"; };
|
||||
85C98007231D4BE900AAAFB2 /* AnyPublisher+Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AnyPublisher+Response.swift"; sourceTree = "<group>"; };
|
||||
85D527792302BEF30093E9C1 /* TestImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestImage.swift; sourceTree = "<group>"; };
|
||||
85F6042D22A018BB00063320 /* RequestTypeWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestTypeWrapper.swift; sourceTree = "<group>"; };
|
||||
86F3C0EA472C23E786E23CE9 /* Image.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
|
||||
@@ -316,7 +308,6 @@
|
||||
331A6D3090D9773091435406 /* Moya */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
85C97FFE231D2D2D00AAAFB2 /* Combine */,
|
||||
149749421F8923EC00FA4900 /* AnyEncodable.swift */,
|
||||
5C2B20158E599EDBE51D7AB2 /* Cancellable.swift */,
|
||||
3FF1994427C5440527B03B31 /* Endpoint.swift */,
|
||||
@@ -408,16 +399,6 @@
|
||||
path = Plugins;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
85C97FFE231D2D2D00AAAFB2 /* Combine */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
85C98007231D4BE900AAAFB2 /* AnyPublisher+Response.swift */,
|
||||
85C98005231D41E400AAAFB2 /* MoyaPublisher.swift */,
|
||||
85C97FFF231D2D4000AAAFB2 /* MoyaProvider+Combine.swift */,
|
||||
);
|
||||
path = Combine;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
85D527782302B4CC0093E9C1 /* MoyaTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -427,7 +408,6 @@
|
||||
C79C5F376B4A2C3F70051980 /* Error+MoyaSpec.swift */,
|
||||
7F112022D8F42844A7D5CB5C /* ErrorTests.swift */,
|
||||
819334FE5D32EFB82599D482 /* MethodSpec.swift */,
|
||||
85C98001231D3EC700AAAFB2 /* MoyaProvider+CombineSpec.swift */,
|
||||
C841AA621AEC61FAEA0CA019 /* MoyaProvider+ReactiveSpec.swift */,
|
||||
4C7A20CC38EB5A0221E6EA34 /* MoyaProvider+RxSpec.swift */,
|
||||
82E52DC541FD052ABA625D2A /* MoyaProviderIntegrationTests.swift */,
|
||||
@@ -854,21 +834,18 @@
|
||||
49C61E884A595E94758B5643 /* Endpoint.swift in Sources */,
|
||||
FB223B5C3B7D4AA5261E25EA /* Image.swift in Sources */,
|
||||
EDBA10DB0D0E35C1474AAB4D /* Moya+Alamofire.swift in Sources */,
|
||||
85C98000231D2D4000AAAFB2 /* MoyaProvider+Combine.swift in Sources */,
|
||||
15D3A2BD1223B59E2BBE09F0 /* MoyaError.swift in Sources */,
|
||||
59BC4B9B9D0D6F9C060E5620 /* MoyaProvider+Defaults.swift in Sources */,
|
||||
149749431F8923EC00FA4900 /* AnyEncodable.swift in Sources */,
|
||||
9854C1DBF14818CCA76AEC7F /* MoyaProvider+Internal.swift in Sources */,
|
||||
147E26EC1F5B14B300C1F513 /* Task.swift in Sources */,
|
||||
149749451F892E2F00FA4900 /* URLRequest+Encoding.swift in Sources */,
|
||||
85C98008231D4BE900AAAFB2 /* AnyPublisher+Response.swift in Sources */,
|
||||
5BCAACCA268FEA0DAB07F998 /* MoyaProvider.swift in Sources */,
|
||||
61633F6E85FB39A4707A6167 /* MultipartFormData.swift in Sources */,
|
||||
5054F87AFF61EAC0097F88BD /* MultiTarget.swift in Sources */,
|
||||
BEAA605B30BE7651BA5C61A4 /* Plugin.swift in Sources */,
|
||||
83B0E400A7562256224CB7FF /* AccessTokenPlugin.swift in Sources */,
|
||||
B5A7124CF285D8EC7F89C1AD /* CredentialsPlugin.swift in Sources */,
|
||||
85C98006231D41E400AAAFB2 /* MoyaPublisher.swift in Sources */,
|
||||
1446FBB31F214C5200C1EFF2 /* URL+Moya.swift in Sources */,
|
||||
4A609CED953E8A6C59AD01A1 /* NetworkActivityPlugin.swift in Sources */,
|
||||
1FD44D9E21CEA6B6221807EF /* NetworkLoggerPlugin.swift in Sources */,
|
||||
@@ -926,7 +903,6 @@
|
||||
files = (
|
||||
A6304A7E74FA3B04C9B10B63 /* AccessTokenPluginSpec.swift in Sources */,
|
||||
2C7132B56A7B129E12BAACAC /* EndpointSpec.swift in Sources */,
|
||||
85C98002231D3EC700AAAFB2 /* MoyaProvider+CombineSpec.swift in Sources */,
|
||||
78A2D3991F44BACD00C9E122 /* RxTestHelpers.swift in Sources */,
|
||||
53376123902C6A22A44DB88E /* Error+MoyaSpec.swift in Sources */,
|
||||
78A2D39B1F44D45100C9E122 /* Single+MoyaSpec.swift in Sources */,
|
||||
@@ -1161,9 +1137,6 @@
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
OTHER_LDFLAGS = $OTHER_LDFLAGS_XCODE11;
|
||||
OTHER_LDFLAGS_XCODE10 = "";
|
||||
OTHER_LDFLAGS_XCODE11 = "-weak_framework Combine";
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -1485,9 +1458,6 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.12;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_LDFLAGS = $OTHER_LDFLAGS_XCODE11;
|
||||
OTHER_LDFLAGS_XCODE10 = "";
|
||||
OTHER_LDFLAGS_XCODE11 = "-weak_framework Combine";
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@
|
||||
"repositoryURL": "https://github.com/Alamofire/Alamofire.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "c1d14588e5558a3669fd03510d135d88c5109069",
|
||||
"version": "5.0.0-rc.2"
|
||||
"revision": "2cbf59935fbb1f26e352ce4db53f1cf9408d5313",
|
||||
"version": "5.0.0-rc.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ let shouldTest = ProcessInfo.processInfo.environment["TEST"] == "1"
|
||||
|
||||
func resolveDependencies() -> [Package.Dependency] {
|
||||
let baseDependencies: [Package.Dependency] = [
|
||||
.package(url: "https://github.com/Alamofire/Alamofire.git", .exact("5.0.0-rc.2")),
|
||||
.package(url: "https://github.com/Alamofire/Alamofire.git", .exact("5.0.0-rc.3")),
|
||||
.package(url: "https://github.com/Moya/ReactiveSwift.git", .upToNextMajor(from: "6.1.0")),
|
||||
.package(url: "https://github.com/ReactiveX/RxSwift.git", .upToNextMajor(from: "5.0.0"))
|
||||
]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<img height="160" src="web/logo_github.png" />
|
||||
</p>
|
||||
|
||||
# Moya
|
||||
# Moya 14.0.0-beta.5
|
||||
|
||||
[](https://circleci.com/gh/Moya/Moya/tree/master)
|
||||
[](https://codecov.io/github/Moya/Moya?branch=master)
|
||||
@@ -76,7 +76,7 @@ _Note: If you are using Swift 4.2 in your project, but you are using Xcode 10.2,
|
||||
To integrate using Apple's Swift package manager, add the following as a dependency to your `Package.swift`:
|
||||
|
||||
```swift
|
||||
.package(url: "https://github.com/Moya/Moya.git", .upToNextMajor(from: "13.0.0"))
|
||||
.package(url: "https://github.com/Moya/Moya.git", .upToNextMajor(from: "14.0.0"))
|
||||
```
|
||||
|
||||
and then specify `"Moya"` as a dependency of the Target in which you wish to use Moya.
|
||||
@@ -95,7 +95,7 @@ let package = Package(
|
||||
targets: ["MyPackage"]),
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/Moya/Moya.git", .upToNextMajor(from: "13.0.0"))
|
||||
.package(url: "https://github.com/Moya/Moya.git", .upToNextMajor(from: "14.0.0"))
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
@@ -116,15 +116,15 @@ Note: If you are using **ReactiveMoya**, we are using [our own fork of ReactiveS
|
||||
For Moya, use the following entry in your Podfile:
|
||||
|
||||
```rb
|
||||
pod 'Moya', '~> 13.0'
|
||||
pod 'Moya', '~> 14.0'
|
||||
|
||||
# or
|
||||
|
||||
pod 'Moya/RxSwift', '~> 13.0'
|
||||
pod 'Moya/RxSwift', '~> 14.0'
|
||||
|
||||
# or
|
||||
|
||||
pod 'Moya/ReactiveSwift', '~> 13.0'
|
||||
pod 'Moya/ReactiveSwift', '~> 14.0'
|
||||
```
|
||||
|
||||
Then run `pod install`.
|
||||
@@ -140,7 +140,7 @@ generated framework they'd like, `Moya`, `RxMoya`, or `ReactiveMoya`.
|
||||
Make the following entry in your Cartfile:
|
||||
|
||||
```
|
||||
github "Moya/Moya" ~> 13.0
|
||||
github "Moya/Moya" ~> 14.0
|
||||
```
|
||||
|
||||
Then run `carthage update`.
|
||||
@@ -149,16 +149,6 @@ If this is your first time using Carthage in the project, you'll need to go thro
|
||||
|
||||
> NOTE: At this time, Carthage does not provide a way to build only specific repository submodules. All submodules and their dependencies will be built with the above command. However, you don't need to copy frameworks you aren't using into your project. For instance, if you aren't using `ReactiveSwift`, feel free to delete that framework along with `ReactiveMoya` from the Carthage Build directory after `carthage update` completes. Or if you are using `ReactiveSwift` but not `RxSwift`, then `RxMoya`, `RxTest`, `RxCocoa`, etc. can safely be deleted.
|
||||
|
||||
#### Moya 14+, Carthage and Xcode 10
|
||||
|
||||
If you are using this specific stack (no SPM/CocoaPods, no Xcode 11), you need to do a little bit more in order to install Moya. This is because Xcode 10 doesn't see Combine as a framework and so it cannot "weakly link it".
|
||||
Below is a script that should get you through the installation process:
|
||||
```bash
|
||||
carthage update Moya --platform iOS --no-build
|
||||
./Carthage/Checkouts/Moya/scripts/carthage-xcode10-compat.sh
|
||||
carthage build Moya --platform iOS
|
||||
```
|
||||
|
||||
### Manually
|
||||
|
||||
- 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:
|
||||
|
||||
+7
-7
@@ -2,7 +2,7 @@
|
||||
<img height="160" src="web/logo_github.png" />
|
||||
</p>
|
||||
|
||||
# Moya
|
||||
# Moya 14.0.0-beta.5
|
||||
|
||||
[](https://circleci.com/gh/Moya/Moya/tree/master)
|
||||
[](https://codecov.io/github/Moya/Moya?branch=master)
|
||||
@@ -61,7 +61,7 @@ Moya 的一些特色功能:
|
||||
要使用苹果的 Swift Package Manager 集成,将以下内容作为依赖添加到你的 `Package.swift`:
|
||||
|
||||
```swift
|
||||
.package(url: "https://github.com/Moya/Moya.git", .upToNextMajor(from: "13.0.0"))
|
||||
.package(url: "https://github.com/Moya/Moya.git", .upToNextMajor(from: "14.0.0"))
|
||||
```
|
||||
|
||||
然后指定 `"Moya"` 为你想要使用 Moya 的 Target 的依赖。如果你想要使用响应式扩展,将 `"ReactiveMoya"` 和 `"RxMoya"` 也也作为依赖加入进来。这里是一个 `PackageDescription` 实例:
|
||||
@@ -78,7 +78,7 @@ let package = Package(
|
||||
targets: ["MyPackage"]),
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/Moya/Moya.git", .upToNextMajor(from: "13.0.0"))
|
||||
.package(url: "https://github.com/Moya/Moya.git", .upToNextMajor(from: "14.0.0"))
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
@@ -95,15 +95,15 @@ let package = Package(
|
||||
在你的 Podfile 文件中添加 Moya:
|
||||
|
||||
```rb
|
||||
pod 'Moya', '~> 13.0'
|
||||
pod 'Moya', '~> 14.0'
|
||||
|
||||
# or
|
||||
|
||||
pod 'Moya/RxSwift', '~> 13.0'
|
||||
pod 'Moya/RxSwift', '~> 14.0'
|
||||
|
||||
# or
|
||||
|
||||
pod 'Moya/ReactiveSwift', '~> 13.0'
|
||||
pod 'Moya/ReactiveSwift', '~> 14.0'
|
||||
```
|
||||
|
||||
然后运行 `pod install`。
|
||||
@@ -117,7 +117,7 @@ Carthage 用户可以指向这个仓库并使用他们喜欢的生成框架,`M
|
||||
在你的 Cartfile 中添加下面的代码:
|
||||
|
||||
```
|
||||
github "Moya/Moya" ~> 13.0
|
||||
github "Moya/Moya" ~> 14.0
|
||||
```
|
||||
|
||||
然后运行 `carthage update`。
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
#if canImport(Combine)
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
#if canImport(UIKit)
|
||||
import UIKit.UIImage
|
||||
#elseif canImport(AppKit)
|
||||
import AppKit.NSImage
|
||||
#endif
|
||||
|
||||
/// Extension for processing raw NSData generated by network access.
|
||||
@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
|
||||
public extension AnyPublisher where Output == Response, Failure == MoyaError {
|
||||
|
||||
/// Filters out responses that don't fall within the given range, generating errors when others are encountered.
|
||||
func filter<R: RangeExpression>(statusCodes: R) -> AnyPublisher<Response, MoyaError> where R.Bound == Int {
|
||||
unwrapThrowable { response in
|
||||
try response.filter(statusCodes: statusCodes)
|
||||
}
|
||||
}
|
||||
|
||||
/// Filters out responses that has the specified `statusCode`.
|
||||
func filter(statusCode: Int) -> AnyPublisher<Response, MoyaError> {
|
||||
unwrapThrowable { response in
|
||||
try response.filter(statusCode: statusCode)
|
||||
}
|
||||
}
|
||||
|
||||
/// Filters out responses where `statusCode` falls within the range 200 - 299.
|
||||
func filterSuccessfulStatusCodes() -> AnyPublisher<Response, MoyaError> {
|
||||
unwrapThrowable { response in
|
||||
try response.filterSuccessfulStatusCodes()
|
||||
}
|
||||
}
|
||||
|
||||
/// Filters out responses where `statusCode` falls within the range 200 - 399
|
||||
func filterSuccessfulStatusAndRedirectCodes() -> AnyPublisher<Response, MoyaError> {
|
||||
unwrapThrowable { response in
|
||||
try response.filterSuccessfulStatusAndRedirectCodes()
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps data received from the signal into an Image. If the conversion fails, the signal errors.
|
||||
func mapImage() -> AnyPublisher<Image, MoyaError> {
|
||||
unwrapThrowable { response in
|
||||
try response.mapImage()
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps data received from the signal into a JSON object. If the conversion fails, the signal errors.
|
||||
func mapJSON(failsOnEmptyData: Bool = true) -> AnyPublisher<Any, MoyaError> {
|
||||
unwrapThrowable { response in
|
||||
try response.mapJSON(failsOnEmptyData: failsOnEmptyData)
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps received data at key path into a String. If the conversion fails, the signal errors.
|
||||
func mapString(atKeyPath keyPath: String? = nil) -> AnyPublisher<String, MoyaError> {
|
||||
unwrapThrowable { response in
|
||||
try response.mapString(atKeyPath: keyPath)
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps received data at key path into a Decodable object. If the conversion fails, the signal errors.
|
||||
func map<D: Decodable>(_ type: D.Type, atKeyPath keyPath: String? = nil, using decoder: JSONDecoder = JSONDecoder(), failsOnEmptyData: Bool = true) -> AnyPublisher<D, MoyaError> {
|
||||
unwrapThrowable { response in
|
||||
try response.map(type, atKeyPath: keyPath, using: decoder, failsOnEmptyData: failsOnEmptyData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
|
||||
public extension AnyPublisher where Output == ProgressResponse, Failure == MoyaError {
|
||||
|
||||
/**
|
||||
Filter completed progress response and maps to actual response
|
||||
|
||||
- returns: response associated with ProgressResponse object
|
||||
*/
|
||||
func filterCompleted() -> AnyPublisher<Response, MoyaError> {
|
||||
self
|
||||
.compactMap { $0.response }
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
/**
|
||||
Filter progress events of current ProgressResponse
|
||||
|
||||
- returns: observable of progress events
|
||||
*/
|
||||
func filterProgress() -> AnyPublisher<Double, MoyaError> {
|
||||
self
|
||||
.filter { !$0.completed }
|
||||
.map { $0.progress }
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
||||
@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
|
||||
extension AnyPublisher where Failure == MoyaError {
|
||||
|
||||
// Workaround for a lot of things, actually. We don't have Publishers.Once, flatMap
|
||||
// that can throw and a lot more. So this monster was created because of that. Sorry.
|
||||
private func unwrapThrowable<T>(throwable: @escaping (Output) throws -> T) -> AnyPublisher<T, MoyaError> {
|
||||
self.tryMap { element in
|
||||
try throwable(element)
|
||||
}
|
||||
.mapError { error -> MoyaError in
|
||||
if let moyaError = error as? MoyaError {
|
||||
return moyaError
|
||||
} else {
|
||||
return .underlying(error, nil)
|
||||
}
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,62 +0,0 @@
|
||||
#if canImport(Combine)
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
|
||||
public extension MoyaProvider {
|
||||
|
||||
/// Designated request-making method.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - target: Entity, which provides specifications necessary for a `MoyaProvider`.
|
||||
/// - callbackQueue: Callback queue. If nil - queue from provider initializer will be used.
|
||||
/// - Returns: `AnyPublisher<Response, MoyaError`
|
||||
func requestPublisher(_ target: Target, callbackQueue: DispatchQueue? = nil) -> AnyPublisher<Response, MoyaError> {
|
||||
MoyaPublisher { [weak self] subscriber in
|
||||
self?.request(target, callbackQueue: callbackQueue, progress: nil) { result in
|
||||
switch result {
|
||||
case let .success(response):
|
||||
_ = subscriber.receive(response)
|
||||
subscriber.receive(completion: .finished)
|
||||
case let .failure(error):
|
||||
subscriber.receive(completion: .failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
/// Designated request-making method with progress.
|
||||
func requestWithProgressPublisher(_ target: Target, callbackQueue: DispatchQueue? = nil) -> AnyPublisher<ProgressResponse, MoyaError> {
|
||||
let progressBlock: (AnySubscriber<ProgressResponse, MoyaError>) -> (ProgressResponse) -> Void = { subscriber in
|
||||
{ progress in
|
||||
_ = subscriber.receive(progress)
|
||||
}
|
||||
}
|
||||
|
||||
let response = MoyaPublisher<ProgressResponse> { [weak self] subscriber in
|
||||
let cancellableToken = self?.request(target, callbackQueue: callbackQueue, progress: progressBlock(subscriber)) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
subscriber.receive(completion: .finished)
|
||||
case let .failure(error):
|
||||
subscriber.receive(completion: .failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
return cancellableToken
|
||||
}
|
||||
|
||||
// Accumulate all progress and combine them when the result comes
|
||||
return response
|
||||
.scan(ProgressResponse()) { last, progress in
|
||||
let progressObject = progress.progressObject ?? last.progressObject
|
||||
let response = progress.response ?? last.response
|
||||
return ProgressResponse(progress: progressObject, response: response)
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
#if canImport(Combine)
|
||||
|
||||
import Combine
|
||||
|
||||
// This should be already provided in Combine, but it's not.
|
||||
// Ideally we would like to remove it, in favor of a framework-provided solution, ASAP.
|
||||
|
||||
@available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
|
||||
internal class MoyaPublisher<Output>: Publisher {
|
||||
|
||||
internal typealias Failure = MoyaError
|
||||
|
||||
private class Subscription: Combine.Subscription {
|
||||
|
||||
private let cancellable: Cancellable?
|
||||
|
||||
init(subscriber: AnySubscriber<Output, MoyaError>, callback: @escaping (AnySubscriber<Output, MoyaError>) -> Cancellable?) {
|
||||
self.cancellable = callback(subscriber)
|
||||
}
|
||||
|
||||
func request(_ demand: Subscribers.Demand) {
|
||||
// We don't care for the demand right now
|
||||
}
|
||||
|
||||
func cancel() {
|
||||
cancellable?.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
private let callback: (AnySubscriber<Output, MoyaError>) -> Cancellable?
|
||||
|
||||
init(callback: @escaping (AnySubscriber<Output, MoyaError>) -> Cancellable?) {
|
||||
self.callback = callback
|
||||
}
|
||||
|
||||
internal func receive<S>(subscriber: S) where S: Subscriber, Failure == S.Failure, Output == S.Input {
|
||||
let subscription = Subscription(subscriber: AnySubscriber(subscriber), callback: callback)
|
||||
subscriber.receive(subscription: subscription)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,342 +0,0 @@
|
||||
#if canImport(Combine)
|
||||
import Quick
|
||||
import Nimble
|
||||
import Combine
|
||||
|
||||
#if canImport(OHHTTPStubs)
|
||||
import OHHTTPStubs
|
||||
#elseif canImport(OHHTTPStubsSwift)
|
||||
import OHHTTPStubsCore
|
||||
import OHHTTPStubsSwift
|
||||
#endif
|
||||
|
||||
@testable import Moya
|
||||
|
||||
final class MoyaProviderCombineSpec: QuickSpec {
|
||||
|
||||
override func spec() {
|
||||
if #available(OSX 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *) {
|
||||
describe("provider") {
|
||||
var provider: MoyaProvider<GitHub>!
|
||||
|
||||
beforeEach {
|
||||
provider = MoyaProvider<GitHub>(stubClosure: MoyaProvider.immediatelyStub)
|
||||
}
|
||||
|
||||
it("emits one Response object") {
|
||||
var calls = 0
|
||||
|
||||
_ = provider.requestPublisher(.zen)
|
||||
.sink(receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case let .failure(error):
|
||||
fail("errored: \(error)")
|
||||
default:
|
||||
()
|
||||
}
|
||||
}, receiveValue: { _ in
|
||||
calls += 1
|
||||
})
|
||||
|
||||
expect(calls).to(equal(1))
|
||||
}
|
||||
|
||||
it("emits stubbed data for zen request") {
|
||||
var responseData: Data?
|
||||
|
||||
let target: GitHub = .zen
|
||||
_ = provider.requestPublisher(target)
|
||||
.sink(receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case let .failure(error):
|
||||
fail("errored: \(error)")
|
||||
default:
|
||||
()
|
||||
}
|
||||
}, receiveValue: { response in
|
||||
responseData = response.data
|
||||
})
|
||||
|
||||
expect(responseData).to(equal(target.sampleData))
|
||||
}
|
||||
|
||||
it("maps JSON data correctly for user profile request") {
|
||||
var receivedResponse: [String: Any]?
|
||||
|
||||
let target: GitHub = .userProfile("ashfurrow")
|
||||
_ = provider.requestPublisher(target)
|
||||
.mapJSON()
|
||||
.sink(receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case let .failure(error):
|
||||
fail("errored: \(error)")
|
||||
default:
|
||||
()
|
||||
}
|
||||
}, receiveValue: { response in
|
||||
receivedResponse = response as? [String: Any]
|
||||
})
|
||||
|
||||
expect(receivedResponse).toNot(beNil())
|
||||
}
|
||||
}
|
||||
|
||||
describe("failing") {
|
||||
var provider: MoyaProvider<GitHub>!
|
||||
|
||||
beforeEach {
|
||||
provider = MoyaProvider<GitHub>(endpointClosure: failureEndpointClosure, stubClosure: MoyaProvider.immediatelyStub)
|
||||
}
|
||||
|
||||
it("emits the correct error message") {
|
||||
var receivedError: MoyaError?
|
||||
|
||||
_ = provider.requestPublisher(.zen)
|
||||
.sink(receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case let .failure(error):
|
||||
receivedError = error
|
||||
case .finished:
|
||||
()
|
||||
}
|
||||
}, receiveValue: { _ in
|
||||
fail("should have errored")
|
||||
})
|
||||
|
||||
switch receivedError {
|
||||
case .some(.underlying(let error, _)):
|
||||
expect(error.localizedDescription) == "Houston, we have a problem"
|
||||
default:
|
||||
fail("expected an Underlying error that Houston has a problem")
|
||||
}
|
||||
}
|
||||
|
||||
it("emits an error") {
|
||||
var errored = false
|
||||
|
||||
let target: GitHub = .zen
|
||||
_ = provider.requestPublisher(target)
|
||||
.sink(receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .failure:
|
||||
errored = true
|
||||
case .finished:
|
||||
()
|
||||
}
|
||||
}, receiveValue: { _ in
|
||||
fail("should have errored")
|
||||
})
|
||||
|
||||
expect(errored).to(beTrue())
|
||||
}
|
||||
}
|
||||
|
||||
describe("a reactive provider") {
|
||||
var provider: MoyaProvider<GitHub>!
|
||||
|
||||
beforeEach {
|
||||
OHHTTPStubs.stubRequests(passingTest: {$0.url!.path == "/zen"}, withStubResponse: { _ in
|
||||
OHHTTPStubsResponse(data: GitHub.zen.sampleData, statusCode: 200, headers: nil)
|
||||
})
|
||||
provider = MoyaProvider<GitHub>(trackInflights: true)
|
||||
}
|
||||
|
||||
it("emits identical response for inflight requests") {
|
||||
let target: GitHub = .zen
|
||||
let signalProducer1 = provider.requestPublisher(target)
|
||||
let signalProducer2 = provider.requestPublisher(target)
|
||||
|
||||
expect(provider.inflightRequests.keys.count).to(equal(0))
|
||||
|
||||
var receivedResponse: Moya.Response!
|
||||
|
||||
// If we do not name the variable, Combine's Cancellable will cancel itself
|
||||
let cancellable1 = signalProducer1.sink(receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case let .failure(error):
|
||||
fail("errored: \(error)")
|
||||
default:
|
||||
()
|
||||
}
|
||||
}, receiveValue: { response in
|
||||
receivedResponse = response
|
||||
expect(provider.inflightRequests.count).to(equal(1))
|
||||
})
|
||||
|
||||
// If we do not name the variable, Combine's Cancellable will cancel itself
|
||||
let cancellable2 = signalProducer2.sink(receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case let .failure(error):
|
||||
fail("errored: \(error)")
|
||||
default:
|
||||
()
|
||||
}
|
||||
}, receiveValue: { response in
|
||||
expect(receivedResponse).toNot(beNil())
|
||||
expect(receivedResponse).to(beIdenticalToResponse(response))
|
||||
expect(provider.inflightRequests.count).to(equal(1))
|
||||
})
|
||||
|
||||
// This is to silence the warning about unused variables
|
||||
_ = cancellable1
|
||||
_ = cancellable2
|
||||
|
||||
// Allow for network request to complete
|
||||
expect(provider.inflightRequests.count).toEventually(equal(0))
|
||||
}
|
||||
}
|
||||
|
||||
describe("a provider with progress tracking") {
|
||||
var provider: MoyaProvider<GitHubUserContent>!
|
||||
|
||||
beforeEach {
|
||||
//delete downloaded filed before each test
|
||||
let directoryURLs = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)
|
||||
let file = directoryURLs.first!.appendingPathComponent("logo_github.png")
|
||||
try? FileManager.default.removeItem(at: file)
|
||||
|
||||
//`responseTime(-4)` equals to 1000 bytes at a time. The sample data is 4000 bytes.
|
||||
OHHTTPStubs.stubRequests(passingTest: {$0.url!.path.hasSuffix("logo_github.png")}, withStubResponse: { _ in
|
||||
OHHTTPStubsResponse(data: GitHubUserContent.downloadMoyaWebContent("logo_github.png").sampleData, statusCode: 200, headers: nil).responseTime(-4)
|
||||
})
|
||||
provider = MoyaProvider<GitHubUserContent>()
|
||||
}
|
||||
|
||||
it("tracks progress of request") {
|
||||
let target: GitHubUserContent = .downloadMoyaWebContent("logo_github.png")
|
||||
|
||||
let expectedNextProgressValues = [0.25, 0.5, 0.75, 1.0, 1.0]
|
||||
let expectedNextResponseCount = 1
|
||||
let expectedErrorEventsCount = 0
|
||||
let expectedCompletedEventsCount = 1
|
||||
let timeout = 5.0
|
||||
|
||||
var nextProgressValues: [Double] = []
|
||||
var nextResponseCount = 0
|
||||
var errorEventsCount = 0
|
||||
var completedEventsCount = 0
|
||||
|
||||
let cancellable = provider.requestWithProgressPublisher(target)
|
||||
.sink(receiveCompletion: { completion in
|
||||
switch completion {
|
||||
case .failure:
|
||||
errorEventsCount += 1
|
||||
case .finished:
|
||||
completedEventsCount += 1
|
||||
}
|
||||
}, receiveValue: { response in
|
||||
nextProgressValues.append(response.progress)
|
||||
|
||||
if response.response != nil { nextResponseCount += 1 }
|
||||
})
|
||||
|
||||
// This is to silence the warning about unused variables
|
||||
_ = cancellable
|
||||
|
||||
expect(completedEventsCount).toEventually(equal(expectedCompletedEventsCount), timeout: timeout)
|
||||
expect(errorEventsCount).toEventually(equal(expectedErrorEventsCount), timeout: timeout)
|
||||
expect(nextResponseCount).toEventually(equal(expectedNextResponseCount), timeout: timeout)
|
||||
expect(nextProgressValues).toEventually(equal(expectedNextProgressValues), timeout: timeout)
|
||||
}
|
||||
|
||||
describe("a custom callback queue") {
|
||||
var stubDescriptor: OHHTTPStubsDescriptor!
|
||||
|
||||
beforeEach {
|
||||
stubDescriptor = OHHTTPStubs.stubRequests(passingTest: {$0.url!.path == "/zen"}, withStubResponse: { _ in
|
||||
OHHTTPStubsResponse(data: GitHub.zen.sampleData, statusCode: 200, headers: nil)
|
||||
})
|
||||
}
|
||||
|
||||
afterEach {
|
||||
OHHTTPStubs.removeStub(stubDescriptor)
|
||||
}
|
||||
|
||||
describe("a provider with a predefined callback queue") {
|
||||
var provider: MoyaProvider<GitHub>!
|
||||
var callbackQueue: DispatchQueue!
|
||||
|
||||
beforeEach {
|
||||
callbackQueue = DispatchQueue(label: UUID().uuidString)
|
||||
provider = MoyaProvider<GitHub>(callbackQueue: callbackQueue)
|
||||
}
|
||||
|
||||
context("the callback queue is provided with the request") {
|
||||
it("invokes the callback on the request queue") {
|
||||
let requestQueue = DispatchQueue(label: UUID().uuidString)
|
||||
var callbackQueueLabel: String?
|
||||
|
||||
let cancellable = provider.requestPublisher(.zen, callbackQueue: requestQueue)
|
||||
.sink(receiveCompletion: { _ in }, receiveValue: { _ in
|
||||
callbackQueueLabel = DispatchQueue.currentLabel
|
||||
})
|
||||
|
||||
// This is to silence the warning about unused variables
|
||||
_ = cancellable
|
||||
|
||||
expect(callbackQueueLabel).toEventually(equal(requestQueue.label))
|
||||
}
|
||||
}
|
||||
|
||||
context("the queueless request method is invoked") {
|
||||
it("invokes the callback on the provider queue") {
|
||||
var callbackQueueLabel: String?
|
||||
|
||||
let cancellable = provider.requestPublisher(.zen)
|
||||
.sink(receiveCompletion: { _ in }, receiveValue: { _ in
|
||||
callbackQueueLabel = DispatchQueue.currentLabel
|
||||
})
|
||||
// This is to silence the warning about unused variables
|
||||
_ = cancellable
|
||||
|
||||
expect(callbackQueueLabel).toEventually(equal(callbackQueue.label))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe("a provider without a predefined queue") {
|
||||
var provider: MoyaProvider<GitHub>!
|
||||
|
||||
beforeEach {
|
||||
provider = MoyaProvider<GitHub>()
|
||||
}
|
||||
|
||||
context("the queue is provided with the request") {
|
||||
it("invokes the callback on the specified queue") {
|
||||
let requestQueue = DispatchQueue(label: UUID().uuidString)
|
||||
var callbackQueueLabel: String?
|
||||
|
||||
let cancellable = provider.requestPublisher(.zen, callbackQueue: requestQueue)
|
||||
.sink(receiveCompletion: { _ in }, receiveValue: { _ in
|
||||
callbackQueueLabel = DispatchQueue.currentLabel
|
||||
})
|
||||
|
||||
// This is to silence the warning about unused variables
|
||||
_ = cancellable
|
||||
|
||||
expect(callbackQueueLabel).toEventually(equal(requestQueue.label))
|
||||
}
|
||||
}
|
||||
|
||||
context("the queue is not provided with the request") {
|
||||
it("invokes the callback on the main queue") {
|
||||
var callbackQueueLabel: String?
|
||||
|
||||
let cancellable = provider.requestPublisher(.zen)
|
||||
.sink(receiveCompletion: { _ in }, receiveValue: { _ in
|
||||
callbackQueueLabel = DispatchQueue.currentLabel
|
||||
})
|
||||
|
||||
// This is to silence the warning about unused variables
|
||||
_ = cancellable
|
||||
|
||||
expect(callbackQueueLabel).toEventually(equal(DispatchQueue.main.label))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This code is replacing `-weak_framework Combine` with `` for Xcode < 11 builds.
|
||||
# Can be removed once we stop supporting Xcode 9/10.
|
||||
# When removing this script, also:
|
||||
# - remove two user-defined build settings: OTHER_LDFLAGS_XCODE10, OTHER_LDFLAGS_XCODE11
|
||||
# - also remove value for OTHER_LDFLAGS build settings (which is probably gonna equal $OTHER_LDFLAGS_XCODE11)
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
sed -ie 's,OTHER_LDFLAGS = $OTHER_LDFLAGS_XCODE11,OTHER_LDFLAGS = $OTHER_LDFLAGS_XCODE10,g' "$DIR/../Moya.xcodeproj/project.pbxproj"
|
||||
Reference in New Issue
Block a user