一.首先定义一个总的遵守TargetType的协议---方便扩展,在这里可以设置默认的请求方式,方便在写具体的借口枚举时,直接设置path,parameters,省去了还得设置其它必须协议
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协议的枚举,比如说
和账号有关的
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)"]
}
}
}
具体服务相关等等。。。。省略
/// 业务逻辑相关api
enum ServiceAPI {
// MARK: - 搜索
case search(nickname: String)
}
这样写的好处有:
1.不必所有借口都写在一个文件里面,不易查找与修改
2.方便多人开发时,两人都修改同一处代码,提交报错问题。。。
二:设置请求时的请求头,请求超时等等
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
}
}
三:写个网络请求的提供工具--在这里使用第二步的网络请求有关的设置
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() {}
}
四:真正网络请求的工具类:
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: -返回数组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: ())
})
})
网友评论