Skip to content

Instantly share code, notes, and snippets.

@ppth0608
Created July 2, 2019 15:58
Show Gist options
  • Save ppth0608/89b73424bd8356646587ec9f1591d244 to your computer and use it in GitHub Desktop.
Save ppth0608/89b73424bd8356646587ec9f1591d244 to your computer and use it in GitHub Desktop.
How to use RxMoya
import Foundation
public struct Clip: Codable, Equatable {
public var id: Int
public var category: ClipCategory
public var title: String
public var userTitle: String
public var imageURLString: String
public var source: String
public var urlString: String
public var isBookmarked: Bool
public var createdDateString: String
public var updatedDateString: String
public var imageURL: URL? {
return URL(string: imageURLString)
}
public var url: URL? {
return URL(string: urlString)
}
public var createdDate: Date? {
return DateFormatter().date(from: createdDateString)
}
public var updatedDate: Date? {
return DateFormatter().date(from: updatedDateString)
}
public init(category: ClipCategory, urlString: String, userTitle: String) {
self.id = 0
self.category = category
self.title = ""
self.userTitle = userTitle
self.imageURLString = ""
self.source = ""
self.urlString = urlString
self.isBookmarked = false
self.createdDateString = ""
self.updatedDateString = ""
}
public init() {
self.id = 0
self.category = ClipCategory()
self.title = ""
self.userTitle = ""
self.imageURLString = ""
self.source = ""
self.urlString = ""
self.isBookmarked = false
self.createdDateString = ""
self.updatedDateString = ""
}
public enum CodingKeys: String, CodingKey {
case id
case category
case title
case userTitle = "personalTitle"
case source = "sourceOf"
case imageURLString = "thumnailLink"
case urlString = "url"
case isBookmarked = "bookmark"
case createdDateString = "createdDate"
case updatedDateString = "updatedDate"
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = (try? container.decode(Int.self, forKey: .id)) ?? 0
category = (try? container.decode(ClipCategory.self, forKey: .category)) ?? ClipCategory()
title = (try? container.decode(String.self, forKey: .title)) ?? ""
userTitle = (try? container.decode(String.self, forKey: .userTitle)) ?? ""
source = (try? container.decode(String.self, forKey: .source)) ?? ""
imageURLString = (try? container.decode(String.self, forKey: .imageURLString)) ?? ""
urlString = (try? container.decode(String.self, forKey: .urlString)) ?? ""
isBookmarked = (try? container.decode(Bool.self, forKey: .isBookmarked)) ?? false
createdDateString = (try? container.decode(String.self, forKey: .createdDateString)) ?? ""
updatedDateString = (try? container.decode(String.self, forKey: .updatedDateString)) ?? ""
}
static public func == (lhs: Clip, rhs: Clip) -> Bool {
return lhs.id == rhs.id
}
}
import Moya
import RxOptional
import RxSwift
import Model
public struct ClipAPI {
enum APIError: Error {
case invalidUserID
}
let provider: MoyaProvider<ClipTarget>
let userID: Int?
public init(userID: Int?) {
provider = MoyaProvider<ClipTarget>()
self.userID = userID
}
public func recentClips(keyword: String = "") -> Observable<[Clip]> {
guard let userID = userID else { return .error(APIError.invalidUserID) }
return self.provider.rx
.request(.recentClipList(userID: userID, keyword: keyword))
.filterSuccessfulStatusCodes()
.map([Clip].self, atKeyPath: "posts")
.asObservable()
}
public func clips(for category: ClipCategory) -> Observable<[Clip]> {
guard let userID = userID else { return .error(APIError.invalidUserID) }
return self.provider.rx
.request(.categoryClipList(userID: userID, category: category))
.filterSuccessfulStatusCodes()
.map([Clip].self, atKeyPath: "posts")
.asObservable()
}
public func add(with clip: Clip) -> Observable<Clip> {
guard let userID = userID else { return .error(APIError.invalidUserID) }
return self.provider.rx
.request(.addClip(userID: userID, clip: clip))
.filterSuccessfulStatusCodes()
.map(Clip.self)
.asObservable()
}
public func bookmark(with clip: Clip) -> Observable<Clip> {
guard let userID = userID else { return .error(APIError.invalidUserID) }
return self.provider.rx
.request(.bookmark(userID: userID, clip: clip))
.filterSuccessfulStatusCodes()
.map(Clip.self)
.asObservable()
}
}
import Foundation
import Moya
import Model
enum ClipTarget {
case recentClipList(userID: Int, keyword: String)
case categoryClipList(userID: Int, category: ClipCategory)
case addClip(userID: Int, clip: Clip)
case bookmark(userID: Int, clip: Clip)
}
extension ClipTarget: TargetType {
var baseURL: URL { return URL(string: "http://localhost:8080")! }
var path: String {
switch self {
case .recentClipList: return "/posts"
case .categoryClipList(_, let category): return "/categories/\(category.id)/posts"
case .addClip: return "/posts"
case .bookmark(_, let clip): return "/post/\(clip.id)/bookmark"
}
}
var method: Moya.Method {
switch self {
case .recentClipList: return .get
case .categoryClipList: return .get
case .addClip: return .post
case .bookmark: return .put
}
}
var headers: [String : String]? {
var headers = [String : String]()
headers["Content-type"] = "application/json"
switch self {
case .recentClipList(let userID, _):
headers["UserID"] = "\(userID)"
case .categoryClipList(let userID, _):
headers["UserID"] = "\(userID)"
case .addClip(let userID, _):
headers["UserID"] = "\(userID)"
case .bookmark(let userID, _):
headers["UserID"] = "\(userID)"
}
return headers
}
var task: Task {
switch self {
case .recentClipList(_, let keyword):
if keyword.isNotEmpty {
return .requestParameters(parameters: [
"keyword": keyword,
"page": "0",
"size": "100"
], encoding: URLEncoding.queryString)
}
return .requestParameters(parameters: [
"page": "0",
"size": "100"
], encoding: URLEncoding.queryString)
case .categoryClipList:
return .requestParameters(parameters: [
"page": "0",
"size": "100"
], encoding: URLEncoding.queryString)
case .addClip(_ , let clip):
return .requestParameters(parameters: [
"url": clip.urlString,
"personalTitle": clip.userTitle,
"category": [
"id": clip.category.id,
]
], encoding: JSONEncoding.default)
case .bookmark:
return .requestPlain
}
}
var sampleData: Data {
return "".data(using: .utf8)!
}
}
private extension String {
var urlEscaped: String {
return addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
}
var utf8Encoded: Data {
return data(using: .utf8)!
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment