1

我正在尝试在我的 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。

4

0 回答 0