一.首先定義一個總的遵守TargetType的協(xié)議---方便擴展符相,在這里可以設(shè)置默認的請求方式吵聪,方便在寫具體的借口枚舉時经备,直接設(shè)置path,parameters,省去了還得設(shè)置其它必須協(xié)議
extension APIable {
var baseURL: URL {
return URL(string: RequestManager<RequestOutData>.baseUrl)!
}
var method: Moya.Method { return .post }
var task: Task { return .request }
var parameterEncoding: ParameterEncoding { return URLEncoding.default }
var sampleData: Data {
return "".data(using: String.Encoding.utf8)!
}
}
2.按接口使用類型分別定義遵守APIable協(xié)議的枚舉茅坛,比如說
和賬號有關(guān)的
enum AccountAPI {
//MARK: -登錄-
case login(type: LoginPlatform)
}
extension AccountAPI: APIable {
var path: String {
switch self {
case .login(type: let type):
switch type {
case .mobile(account: _, code: _):
return "user/login.do"
case .third(type: let third, openid: _, img: _, nick: _, ifbount: _):
switch third {
case .qq: return "user/qqlogin.do"
case .weixin: return "user/wxlogin.do"
case .weibo: return "user/wblogin.do"
}
}
}
}
var parameters: [String : Any]? {
switch self {
case .login(type: let type):
switch type {
case .mobile(account: let account, code: let code):
return ["account": account, "code": code]
case .third(type: _, openid: let openid, img: let img, nick: let nick, ifbount: let ifbount):
let isOld = ifbount ? 1 : 0
return ["openid": openid, "img": img, "nick": nick, "ifbount": "\(isOld)"]
}
}
}
具體服務(wù)相關(guān)等等音半。。贡蓖。曹鸠。省略
/// 業(yè)務(wù)邏輯相關(guān)api
enum ServiceAPI {
// MARK: - 搜索
case search(nickname: String)
}
這樣寫的好處有:
1.不必所有借口都寫在一個文件里面,不易查找與修改
2.方便多人開發(fā)時斥铺,兩人都修改同一處代碼彻桃,提交報錯問題。晾蜘。邻眷。
二:設(shè)置請求時的請求頭,請求超時等等
extension APIable {
static func endpointClosure<T: APIable>() -> (T) -> Endpoint<T> {
let endpointClosure = { (target: T) -> Endpoint<T> in
let endpoint = Endpoint<T>(
url: target.baseURL.appendingPathComponent(target.path).absoluteString,
sampleResponseClosure: { .networkResponse(200, target.sampleData) },
method: target.method,
parameters: target.parameters,
parameterEncoding: target.parameterEncoding)
if let account = target as? AccountAPI {
switch account {
case .login(type: _), .getCode(mobile: _, mode: _):
return endpoint
default:
return endpoint.adding(
httpHeaderFields: ["userid": "\(PreferenceManager.shared[.userid])",
"appsign": PreferenceManager.shared[.appsign] ?? ""
])
}
} else {
return endpoint.adding(
httpHeaderFields: ["userid": "\(PreferenceManager.shared[.userid])",
"appsign": PreferenceManager.shared[.appsign] ?? ""
])
}
}
return endpointClosure
}
static func requestClosure<T: APIable>() -> (Endpoint<T>, @escaping (Result<URLRequest, MoyaError>) -> Void) -> Void {
let requestC = { (endpoint: Endpoint<T>, done: @escaping ((Result<URLRequest, MoyaError>) -> Void)) in
if let urlRequest = endpoint.urlRequest {
var request = urlRequest
request.timeoutInterval = 10
done(.success(request))
} else {
done(.failure(MoyaError.requestMapping(endpoint.url)))
}
}
return requestC
}
}
三:寫個網(wǎng)絡(luò)請求的提供工具--在這里使用第二步的網(wǎng)絡(luò)請求有關(guān)的設(shè)置
private struct ProviderManager {
static let shared = ProviderManager()
let apiProvider = ReactiveSwiftMoyaProvider<AccountAPI>(
endpointClosure: AccountAPI.endpointClosure(),
requestClosure: AccountAPI.requestClosure(),
plugins: [NetworkActivityPlugin { UIApplication.shared.isNetworkActivityIndicatorVisible = $0 == .began },
NetworkLoggerPlugin(verbose: true)]
)
let serviceProvider = ReactiveSwiftMoyaProvider<ServiceAPI>(
endpointClosure: ServiceAPI.endpointClosure(),
requestClosure: ServiceAPI.requestClosure(),
plugins: [NetworkActivityPlugin { UIApplication.shared.isNetworkActivityIndicatorVisible = $0 == .began },
NetworkLoggerPlugin(verbose: true)]
)
private init() {}
}
四:真正網(wǎng)絡(luò)請求的工具類:
struct RequestManager<Base> where Base: Mappable {
private init() {}
static var baseUrl: String { return BaseUrl.net.rawValue }
//MARK: -返回單個model-
static func requesObject(_ api: APIable) -> SignalProducer<Base, NetError> {
let status = RealReachability.sharedInstance().currentReachabilityStatus()
switch status {
case .RealStatusNotReachable, .RealStatusUnknown:
return SignalProducer<Base, NetError>(error: .content)
case .RealStatusViaWiFi, .RealStatusViaWWAN:
if let account = api as? AccountAPI {
let producer: SignalProducer<Base, NetError> =
ProviderManager.shared.apiProvider
.request(account)
.toObject()
return producer
}
else if let service = api as? ServiceAPI {
let producer: SignalProducer<Base, NetError> =
ProviderManager.shared.serviceProvider
.request(service)
.toObject()
return producer
}
else {
fatalError()
}
}
}
//MARK: -返回數(shù)組model-
static func requestArray(_ api: TargetType) -> SignalProducer<[Base], NetError> {
let status = RealReachability.sharedInstance().currentReachabilityStatus()
switch status {
case .RealStatusNotReachable, .RealStatusUnknown:
return SignalProducer<[Base], NetError>(error: .content)
case .RealStatusViaWiFi, .RealStatusViaWWAN:
if let account = api as? AccountAPI {
let producer: SignalProducer<[Base], NetError> =
ProviderManager.shared.apiProvider
.request(account)
.toArray()
return producer
}
else if let service = api as? ServiceAPI {
let producer: SignalProducer<[Base], NetError> =
ProviderManager.shared.serviceProvider
.request(service)
.toArray()
return producer
}
else {
fatalError()
}
}
}
}
五: 外界使用:
searchAction: Action<String, Void, NetError> = Action({ nick in
return RequestManager<SessionUser>
.requestArray(ServiceAPI.search(nickname: nick))
.map({ sessionUsers in
self.result.value = sessionUsers.map { $0.user }
reloadObserver.send(value: ())
})
})