ios 如何使用结果库处理无效成功情况(成功/失败)

nhhxz33t  于 2024-01-09  发布在  iOS
关注(0)|答案(4)|浏览(165)

简介

我在我的应用程序的某些点引入了Result framework (antitypical)。例如,给定此函数:

func findItem(byId: Int, completion: (Item?,Error?) -> ());

foo.findItem(byId: 1) { item, error in
   guard let item = item else {
       // Error case
       handleError(error!)
       return;
   }
   // Success case
   handleSuccess(item)
}

字符串
我用Result实现它:

func findItem(byId: Int, completion: Result<Item,Error>) -> ());

foo.findItem(byId: 1) { result in
   swith result {
      case let success(item):
         // Success case
         handleSuccess(item)
      case let failure(error):
         // Error case
         handleError(error!)
   }
}

Question当success case不返回任何结果时,正确的实现方法是什么?。类似于:

func deleteItem(byId: Int, completion: (Error?) -> ());

foo.deleteItem(byId: 1) { error in
   if let error = error {
       // Error case
       handleError(error)
       return;
   }
   // Success case
   handleSuccess()
}


在java中,我会实现一个Result,在Swift中正确的方法是什么?

hs1rzwqc

hs1rzwqc1#

最好的方法就是你所做的:Error?,其中nil表示成功。它非常清晰和简单。
也就是说,另一个答案(也是我用过的)正好在你的问题中:“如何用Result处理Void成功案例。”成功案例传递Void,所以传递Void

Result<Void, Error>

字符串
“Void”并不意味着“什么都不返回”。它是Swift中的一种类型,一种只有一个值的类型:空元组()。这也恰好是类型:

public typealias Void = ()


按照惯例,我们使用Void表示类型,使用()表示值。在Result中使用Void的语法有点奇怪。你最终会得到这样的结果:

return .success(())


双括号有点难看,有点令人困惑。因此,尽管这与其他使用Result的代码很好地并行,但在这种情况下,我通常只使用Error?。如果我有很多这样的代码,我会考虑为它创建一个新类型:

enum VoidResult {
    case success
    case failure(Error)
}

bpzcxfmw

bpzcxfmw2#

您可以添加此扩展,以简化您的生活。

public extension Result where Success == Void {
    
    /// A success, storing a Success value.
    ///
    /// Instead of `.success(())`, now  `.success`
    static var success: Result {
        return .success(())
    }
}

// Now
return .success

字符串
Gists

rbl8hiat

rbl8hiat3#

我发现Rob的回答非常有趣和聪明。我只是想贡献一个可能的工作解决方案来帮助他人:

enum VoidResult {
    case success
    case failure(Error)
}

/// Performs a request that expects no data back but its success depends on the result code
/// - Parameters:
///   - urlRequest: Url request with the request config
///   - httpMethodType: HTTP method to be used: GET, POST ...
///   - params: Parameters to be included with the request
///   - headers: Headers to be included with the request
///   - completion: Callback trigered upon completion
func makeRequest(url: URL,
                 httpMethodType: HTTPMethodType,
                 params: [String:Any],
                 headers: [String:String],
                 completion: @escaping (VoidResult) -> Void){
    let alamofireHTTPMethod = httpMethodType.toAlamofireHTTPMethod()
    
    let parameterEncoder: ParameterEncoding
    switch alamofireHTTPMethod {
    case .get:
        parameterEncoder = URLEncoding.default
    case .post:
        parameterEncoder = JSONEncoding.default
    default:
        parameterEncoder = URLEncoding.default
    }
    
    Log.d(message: "Calling: \(url.absoluteString)")
    AF.request(url,
               method: alamofireHTTPMethod,
               parameters: params,
               encoding:parameterEncoder,
               headers: HTTPHeaders(headers)).response { response in
                guard let statusCode = response.response?.statusCode,
                    (200 ..< 300) ~= statusCode else {
                        completion(.failure(NetworkFetcherError.networkError))
                        return
                }
                completion(.success)
                
    }
    
  }

字符串

6qqygrtg

6qqygrtg4#

试试这个

请注意,这是一个示例,您可以根据测试进行更改

typealias resultHandler = (_ responseItems: AnyObject, _ error: Error) -> Void

func deleteItem(byId: Int, completion: resultHandler){
       completion(Items, error) 
 }

字符串

呼唤

self.deleteItem(byId: 1) { (result, error) in
            if error ==nil{

            }
        }

相关问题