2016-08-08 20 views
2

私のコードで成功と失敗の呼び出しのためのメソッドチェインを実装しようとしていますが、実際にはonSuccessメソッドを呼び出すのに問題があるようです。成功と失敗によるスウィフトメソッドチェイン

  1. ビューコントローラは、getProduct(_:)関数を呼び出します。
  2. getProduct(_:)は、APIの呼び出しを行い、その後、
  3. storeProduct(_:)通話fetchProduct(_:)
  4. fetchProduct(_:)通話doSuccess(_:)取得したJSONとstoreProduct(_:)を呼び出しますが、これは決して以前の呼び出しのonSuccessに戻って得ません。

いくつかのコードスニペット

BSProductChainable.swift

import Foundation 

class BSProductChainable<SuccessParams, FailureParams> { 

    var successClosure: ((SuccessParams) ->())? = nil 
    var failureClosure: ((FailureParams) ->())? = nil 

    func onSuccess(closure: (SuccessParams) ->()) -> BSProductChainable { 
     successClosure = closure 
     return self 
    } 
    func onFailure(closure: (FailureParams) ->()) -> 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) 
     } 
    } 
} 

BSProductManagerSwift.swift

class BSProductManagerSwift: NSObject { 

typealias productResponseChain = BSProductChainable<Product, NSError?> 
typealias productsResponseChain = BSProductChainable<[Product], NSError?> 

var serviceClient: BSNetworkingServiceClient! 
var objectContext: NSManagedObjectContext! 
var productChains: BSProductChainable<Product, NSError?>! 
var productsChains: BSProductChainable<[Product], NSError?>! 

convenience init(serviceClient: BSNetworkingServiceClient) { 
    self.init() 
    self.serviceClient = serviceClient 
    self.objectContext = managedObjectContext 
    self.productChains = BSProductChainable<Product, NSError?>() 
    self.productsChains = BSProductChainable<[Product], NSError?>() 
} 

func getProduct(ean: String) -> productResponseChain { 

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

    return productChains 
} 

func storeProduct(json: JSON) -> productResponseChain { 

    fetchProduct(json["ean"].stringValue).onSuccess { (returedProduct) in 
     self.productChains.doSuccess(returedProduct) 
    } 

    return productChains 
} 

func fetchProduct(ean: String) -> productResponseChain { 

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

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

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

    return productChains 
} 

私は当初initialis関数ごとに連鎖可能なクラスを作成しましたが、これは独自の問題を抱えていました。連鎖可能なクラスを一度初期化してその参照を渡す必要があると誤って考えていました。

私が間違っている場所については、/私が次に試すことができるものは素晴らしいでしょう。 @ジョンの要素によって推奨されているように

+2

独自のフレームワークを構築するのではなく、フレームワークを使用してみませんか? promisekitを見てみましょう。 https://github.com/mxcl/PromiseKit –

+0

この問題を解決しようとすると、私はすでに多くの時間を費やしてしまったので、私の行くべき方法かもしれません。 – Hodson

答えて

0

は、私は(まだコードのビットを行うために必要なコードの変更の多くに必要としませんでしたPromiseKit

これを使用することを決定し、ここでの機能は、今のように見えるものです):

func getProduct(ean: String) -> Promise<Product> { 
    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("We stored the product: \(returnedProduct.ean)") 
        fullfill(returnedProduct) 
       }).error { returnedError in 
        print("We had a problem storing the product: \(returnedError)") 
       } 
      } 
     } 
    } 
} 

func storeProduct(json: JSON) -> Promise<Product> { 
    return Promise { fullfill, reject in 
     fetchProduct(json["ean"].stringValue).then ({ returnedProduct in 

      var storedProduct: Product! 
      var isNewProduct = false 

      print("Fetched Product: \(returnedProduct.ean)") 

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

      do { 
       try self.objectContext.save() 
       print("Stored Product: \(returnedProduct.ean)") 
       fullfill(returnedProduct) 

       if isNewProduct { 
        NSNotificationCenter.defaultCenter().postNotificationName("DidAddScanEntry", object: nil) 
       } 

      } catch let error as NSError { 
       print("Could not save \(error), \(error.userInfo)") 
       reject(error) 
      } 

     }).error { returnedError in 
      print("We had a problem fetching the product: \(returnedError)") 
      reject(returnedError) 
     } 
    } 
} 

func fetchProduct(ean: String) -> Promise<Product> { 
    return Promise { fullfill, reject in 

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

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

      if matchingProuducts.count == 0 { 
       print("No matching products found") 
       let entity = NSEntityDescription.entityForName("Product", inManagedObjectContext: objectContext) 
       fullfill(Product(entity: entity!, insertIntoManagedObjectContext: objectContext)) 
      } else { 
       print("Found matching product") 
       let d = matchingProuducts.first as! Product 
       fullfill(d) 
      } 
     } catch let error as NSError { 
      print("Could not fetch \(error), \(error.userInfo)") 
      reject(error) 
     } 
    } 
} 
関連する問題