我正在尝试在我的 SwiftUI 项目中调用 api,为此我想在其中创建 BaseService.swift 文件,我将放置 Alamofire 的常用功能,然后我希望在我想调用的此类中创建 ObservableObject 类多个 api 并访问视图上的数据。也许我做错了,请帮助我。
我的 BaseService.Swift 文件
class BaseService: ObservableObject {
// MARK: - Constant or Variable Declarations
let network = NetworkReachabilityManager.init(host: "https://www.google.com")
var myRequest: AlamofireRequestModal?
var successBlock: ((AnyObject?) -> Void)?
var failureBlock: ((NSError?) -> Void)?
// MARK: - Custom Methods
/**
calls web service through Alamofire
- parameter alamoReq: user email address from google info.
- parameter success: reference to success block of callback function
- parameter failure: reference to failure block of callback function
*/
func callWebServiceAlamofire(_ alamoReq: AlamofireRequestModal,
success:@escaping ((_ responseObject: AnyObject?) -> Void),
failure:@escaping ((_ error: NSError?) -> Void)) {
guard (network?.isReachable)! else {
debugPrint("\n No Network Connection")
return failure(generateError(request: alamoReq.apiURL(), code: 503, errors: nil, message: "No Internet Connection"))
}
// saving request data and handlers
myRequest = alamoReq
successBlock = success
failureBlock = failure
// preparing api request
let request = Alamofire.request(alamoReq.apiURL(), method: alamoReq.method, parameters: alamoReq.parameters, encoding: alamoReq.updatedEncoding(), headers: alamoReq.updateRequestHeader())
request.printDescription()
// getting response: call response handler method of alamofire
request.responseJSON(completionHandler: { response in
self.handleReceivedInfo(response, success: success, failure: failure)
})
}
/**
handles received web service response
- parameter receivedInfo: webservice response
- parameter success: reference to success block of callback function
- parameter failure: reference to failure block of callback function
*/
func handleReceivedInfo(_ receivedInfo: DataResponse<Any>,
success:@escaping ((_ responseObject: AnyObject?) -> Void),
failure:@escaping ((_ error: NSError?) -> Void)) {
let statusCode = receivedInfo.response?.statusCode ?? (receivedInfo.result.error as NSError?)?.code ?? 0
let requestURLString = receivedInfo.request?.url?.absoluteString
if statusCode == 401 && !(requestURLString?.contains(API.Path.googleAuthentication) ?? false) {
debugPrint("Refreshing access token")
let path = Configuration().baseURL + API.Path.refreshToken
let token = UserDefaultManager.instance.getAccessToken() ?? ""
let request = Alamofire.request(path, method: .get, parameters: nil, encoding: URLEncoding() as ParameterEncoding, headers: [API.Headers.Authorization: "Bearer \(token)"])
request.printDescription()
request.responseJSON(completionHandler: { response in
if let statusCode = response.response?.statusCode, statusCode == 200 {
if let data = response.data {
if let dict = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableLeaves) as? [String: String] {
UserDefaultManager.instance.setAccessToken(dict[Keys.accessToken])
if let lastRequest = self.myRequest {
self.callWebServiceAlamofire(lastRequest, success: success, failure: failure)
}
} else {
debugPrint("Not found API access token.")
(UIApplication.shared.delegate as? AppDelegate)?.redirectToLoginScreen()
}
} else {
debugPrint("Invalid data.")
(UIApplication.shared.delegate as? AppDelegate)?.redirectToLoginScreen()
}
} else {
(UIApplication.shared.delegate as? AppDelegate)?.redirectToLoginScreen()
}
})
} else {
switch receivedInfo.result {
case .success(let data):
if statusCode == 200 {
if let result = data as? String {
success(result as AnyObject)
} else if let result = data as? Bool {
success(result as AnyObject)
} else if let result = data as? Int {
success(result as AnyObject)
} else {
do {
let jsonData = try JSONSerialization.data(withJSONObject: data, options: JSONSerialization.WritingOptions.prettyPrinted)
success(jsonData as AnyObject)
} catch let msg {
debugPrint("JSON serialization error:" + "\(msg)")
failure(generateError(request: requestURLString, code: statusCode, errors: nil, message: msg as? String))
}
}
} else {
if let errorMessage = (data as? NSDictionary)?.value(forKey: "message") {
failure(generateError(request: requestURLString, code: statusCode, errors: nil, message: errorMessage as? String))
} else {
failure(generateError(request: requestURLString, code: statusCode, errors: nil, message: nil))
}
}
case .failure(_):
if let data = receivedInfo.data {
do {
if let responseObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject] {
var message = ""
if let string = (responseObject as NSDictionary).value(forKey: "message") as? String {
message = string
}
failure(generateError(request: requestURLString, code: statusCode, errors: nil, message: message))
}
} catch let error as NSError {
failure(generateError(request: requestURLString, code: statusCode, errors: nil, message: error.localizedDescription))
}
}
}
}
}
/**
handles api error
- parameter request: web service request url string
- parameter code: api status code
- parameter errors: error info
- parameter message: error message string
*/
func generateError(request: String?, code: Int, errors: [String: Any]?, message: String?) -> NSError? {
var errorMessage = ""
if let error = errors, let value = error.first?.value {
switch value {
case is String:
errorMessage = value as? String ?? ""
case is [String]:
errorMessage = (value as? [String])?.first ?? ""
default:
break
}
} else if let msg = message {
errorMessage = msg
} else {
switch code {
case 500:
errorMessage = "Server Error(500) \nSomething went wrong. Please try again!"
case -1010 ..< -1000:
errorMessage = "We are unable to connect you with the server. Please check your internet connection and try again!"
default:
break
}
}
return NSError.init(domain: "Error", code: code, userInfo: ["message": errorMessage])
}
/**
calls recent API request after token refresh has been completed
- parameter notification: reference to notification observer
*/
@objc func callRecentAPIRequest(_ notification: Notification) {
guard let request = myRequest, let success = successBlock, let failure = failureBlock else {
return
}
callWebServiceAlamofire(request, success: success, failure: failure)
}
}
我的 ObservableObject 类是
class AuthenticationService: BaseService {
/**
It authenticates the google sign in process.
- parameter email: provide the user email address
- parameter token: provide the google access token
- parameter success: returns the success block
- parameter failure: returns the failure block
*/
func googleAuthentication(email: String, token: String, success: @escaping ((_ response: AnyObject?) -> Void), failure: @escaping ((_ error: NSError?) -> Void)) {
var request = AlamofireRequestModal()
request.method = .post
request.path = API.Path.googleAuthentication
request.parameters = [
"username": email as AnyObject,
"google_access_token": token as AnyObject,
"device_type": "3" as AnyObject,
"device_token": UserDefaultManager.instance.getDeviceID() as AnyObject
]
callWebServiceAlamofire(request, success: success, failure: failure)
}
/**
It is used to refresh the access token
- parameter success: returns the success block
- parameter failure: returns the failure block
*/
func refreshAccessToken(success: @escaping ((_ response: AnyObject?) -> Void), failure: @escaping ((_ error: NSError?) -> Void)) {
var request = AlamofireRequestModal()
request.method = .get
request.path = API.Path.refreshToken
callWebServiceAlamofire(request, success: success, failure: failure)
}
/**
It is used to revoke the API access token and sign out the user.
- parameter success: returns the success block
- parameter failure: returns the failure block
*/
func signOut(success: @escaping ((_ response: AnyObject?) -> Void), failure: @escaping ((_ error: NSError?) -> Void)) {
var request = AlamofireRequestModal()
request.method = .get
request.path = API.Path.revokeToken
callWebServiceAlamofire(request, success: success, failure: failure)
}
func updateDeviceToken(success: @escaping ((_ response: AnyObject?) -> Void), failure: @escaping ((_ error: NSError?) -> Void)) {
var request = AlamofireRequestModal()
request.method = .post
request.path = API.Path.updateDeviceToken
request.parameters = [
"device_type": "3" as AnyObject,
"device_id": UserDefaultManager.instance.getDeviceID() as AnyObject,
"gcm_id": UserDefaultManager.instance.getFCMToken() as AnyObject
]
callWebServiceAlamofire(request, success: success, failure: failure)
}
}
现在我想创建 AuthenticationService 对象并访问 googleAuthentication,refereshToken api。