菜鸟教程小白 发表于 2022-12-11 17:12:29

ios - 带有成功和失败的 Swift 方法链


                                            <p><p>我正在尝试在我的代码中为成功和失败调用实现方法链接,但我似乎无法真正调用 <code>onSuccess</code> 方法。</p>

<ol>
<li> ViewController 调用 <code>getProduct(_:)</code> 函数。</li>
<li><code>getProduct(_:)</code> 进行 API 调用,然后使用检索到的 json 调用 <code>storeProduct(_:)</code></li>
<li><code>storeProduct(_:)</code> 调用 <code>fetchProduct(_:)</code></li>
<li><code>fetchProduct(_:)</code> 调用 <code>doSuccess(_:)</code> 但这永远不会回到先前调用的 <code>onSuccess</code> 中。<</li>
</ol>

<p><strong>一些代码片段</strong></p>

<p><em>BSProductChainable.swift</em></p>

<pre><code>import Foundation

class BSProductChainable&lt;SuccessParams, FailureParams&gt; {

    var successClosure: ((SuccessParams) -&gt; ())? = nil
    var failureClosure: ((FailureParams) -&gt; ())? = nil

    func onSuccess(closure: (SuccessParams) -&gt; ()) -&gt; BSProductChainable {
      successClosure = closure
      return self
    }
    func onFailure(closure: (FailureParams) -&gt; ()) -&gt; BSProductChainable {
      failureClosure = closure
      return self
    }
    func doSuccess(params: SuccessParams) {
      if let closure = successClosure {
            closure(params)
      }
    }
    func doFailure(params: FailureParams) {
      if let closure = failureClosure {
            closure(params)
      }
    }
}
</code></pre>

<p><em>BSProductManagerSwift.swift</em></p>

<pre><code>class BSProductManagerSwift: NSObject {

typealias productResponseChain = BSProductChainable&lt;Product, NSError?&gt;
typealias productsResponseChain = BSProductChainable&lt;, NSError?&gt;

var serviceClient: BSNetworkingServiceClient!
var objectContext: NSManagedObjectContext!
var productChains: BSProductChainable&lt;Product, NSError?&gt;!
var productsChains: BSProductChainable&lt;, NSError?&gt;!

convenience init(serviceClient: BSNetworkingServiceClient) {
    self.init()
    self.serviceClient = serviceClient
    self.objectContext = managedObjectContext
    self.productChains = BSProductChainable&lt;Product, NSError?&gt;()
    self.productsChains = BSProductChainable&lt;, NSError?&gt;()
}

func getProduct(ean: String) -&gt; productResponseChain {

    let urlString = BSConstants.BarcodeScanner.productEndpoint.stringByAppendingString(ean)
    serviceClient.GET(urlString, failure: { (error) in
      print(&#34;Could not get product&#34;)
    }) { (response) in
      if let json = response {
            self.storeProduct(json).onSuccess({ (returedProduct) in
                print(&#34;Stored product&#34;)
            })
      }
    }

    return productChains
}

func storeProduct(json: JSON) -&gt; productResponseChain {

    fetchProduct(json[&#34;ean&#34;].stringValue).onSuccess { (returedProduct) in
      self.productChains.doSuccess(returedProduct)
    }

    return productChains
}

func fetchProduct(ean: String) -&gt; productResponseChain {

    let fetchRequest = NSFetchRequest(entityName: &#34;Product&#34;)
    let predicateEAN = NSPredicate(format: &#34;%K == %@&#34;, &#34;ean&#34;, ean)
    let predicateMarket = NSPredicate(format: &#34;%K == %@&#34;, &#34;market&#34;, BSCountryManager.sharedInstance().getCurrentCountry().market)
    let predicateLocale = NSPredicate(format: &#34;%K == %@&#34;, &#34;locale&#34;, BSLocalizationManager.sharedManager().currentLocalization.localeIdentifier())
    let predicateCurrency = NSPredicate(format: &#34;%K == %@&#34;, &#34;currency&#34;, BSLocalizationManager.sharedManager().currentLocalization.country.currencyIdentifierDMW)
    let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: )
    fetchRequest.predicate = compoundPredicate

    do {
      let matchingProuducts = try objectContext.executeFetchRequest(fetchRequest)

      if matchingProuducts.count == 0 {
            print(&#34;No matching products found&#34;)
            let entity = NSEntityDescription.entityForName(&#34;Product&#34;, inManagedObjectContext: objectContext)
            productChains.doSuccess(Product(entity: entity!, insertIntoManagedObjectContext: objectContext))
      } else {
            print(&#34;Found matching product&#34;)
            let d = matchingProuducts.first as! Product
            productChains.doSuccess(d)
      }
    } catch let error as NSError {
      print(&#34;Could not fetch \(error), \(error.userInfo)&#34;)
      productChains.doFailure(error)
    }

    return productChains
}
</code></pre>

<p>我最初为每个函数初始化了可链接类,但这有其自身的问题,我认为(可能是错误的)我应该只初始化可链接类一次并传递它的引用。</p>

<p>关于我哪里出错/接下来我可以尝试什么的一些输入会很棒。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>根据@john elements 的建议,我决定使用 <a href="http://github.com/mxcl/PromiseKit" rel="noreferrer noopener nofollow">PromiseKit</a> </p>

<p>这不需要太多的代码更改,下面是函数现在的样子(仍然需要做一些代码清理,但它可以工作!):<​​/p>

<pre><code>func getProduct(ean: String) -&gt; Promise&lt;Product&gt; {
    return Promise { fullfill, reject in
      let urlString = BSConstants.BarcodeScanner.productEndpoint.stringByAppendingString(ean)
      serviceClient.GET(urlString, failure: { (error) in
            reject(error!)
      }) { (response) in
            if let json = response {
                self.storeProduct(json).then ({ returnedProduct in
                  print(&#34;We stored the product: \(returnedProduct.ean)&#34;)
                  fullfill(returnedProduct)
                }).error { returnedError in
                  print(&#34;We had a problem storing the product: \(returnedError)&#34;)
                }
            }
      }
    }
}

func storeProduct(json: JSON) -&gt; Promise&lt;Product&gt; {
    return Promise { fullfill, reject in
      fetchProduct(json[&#34;ean&#34;].stringValue).then ({ returnedProduct in

            var storedProduct: Product!
            var isNewProduct = false

            print(&#34;Fetched Product: \(returnedProduct.ean)&#34;)

            isNewProduct = returnedProduct.valueForKey(&#34;ean&#34;) == nil
            storedProduct = returnedProduct
            storedProduct.setValue(json[&#34;name&#34;].stringValue, forKey: &#34;name&#34;)
            storedProduct.setValue(json[&#34;ean&#34;].stringValue, forKey: &#34;ean&#34;)
            storedProduct.setValue(json[&#34;image&#34;].stringValue, forKey: &#34;image&#34;)
            storedProduct.setValue(json[&#34;price&#34;].doubleValue, forKey: &#34;price&#34;)
            storedProduct.setValue(json[&#34;status&#34;].intValue, forKey: &#34;status&#34;)
            storedProduct.setValue(json[&#34;pdp&#34;].stringValue, forKey: &#34;pdp&#34;)
            storedProduct.setValue(BSCountryManager.sharedInstance().getCurrentCountry().market, forKey: &#34;market&#34;)
            storedProduct.setValue(BSLocalizationManager.sharedManager().currentLocalization.localeIdentifier(), forKey: &#34;locale&#34;)
            storedProduct.setValue(BSLocalizationManager.sharedManager().currentLocalization.country.currencyIdentifierDMW, forKey: &#34;currency&#34;)

            do {
                try self.objectContext.save()
                print(&#34;Stored Product: \(returnedProduct.ean)&#34;)
                fullfill(returnedProduct)

                if isNewProduct {
                  NSNotificationCenter.defaultCenter().postNotificationName(&#34;DidAddScanEntry&#34;, object: nil)
                }

            } catch let error as NSError {
                print(&#34;Could not save \(error), \(error.userInfo)&#34;)
                reject(error)
            }

      }).error { returnedError in
            print(&#34;We had a problem fetching the product: \(returnedError)&#34;)
            reject(returnedError)
      }
    }
}

func fetchProduct(ean: String) -&gt; Promise&lt;Product&gt; {
    return Promise { fullfill, reject in

      let fetchRequest = NSFetchRequest(entityName: &#34;Product&#34;)
      let predicateEAN = NSPredicate(format: &#34;%K == %@&#34;, &#34;ean&#34;, ean)
      let predicateMarket = NSPredicate(format: &#34;%K == %@&#34;, &#34;market&#34;, BSCountryManager.sharedInstance().getCurrentCountry().market)
      let predicateLocale = NSPredicate(format: &#34;%K == %@&#34;, &#34;locale&#34;, BSLocalizationManager.sharedManager().currentLocalization.localeIdentifier())
      let predicateCurrency = NSPredicate(format: &#34;%K == %@&#34;, &#34;currency&#34;, BSLocalizationManager.sharedManager().currentLocalization.country.currencyIdentifierDMW)
      let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: )
      fetchRequest.predicate = compoundPredicate

      do {
            let matchingProuducts = try objectContext.executeFetchRequest(fetchRequest)

            if matchingProuducts.count == 0 {
                print(&#34;No matching products found&#34;)
                let entity = NSEntityDescription.entityForName(&#34;Product&#34;, inManagedObjectContext: objectContext)
                fullfill(Product(entity: entity!, insertIntoManagedObjectContext: objectContext))
            } else {
                print(&#34;Found matching product&#34;)
                let d = matchingProuducts.first as! Product
                fullfill(d)
            }
      } catch let error as NSError {
            print(&#34;Could not fetch \(error), \(error.userInfo)&#34;)
            reject(error)
      }
    }
}
</code></pre></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 带有成功和失败的 Swift 方法链,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/38832681/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/38832681/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 带有成功和失败的 Swift 方法链