2016-08-08 2 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 함수 당 chainable 클래스를 만들었지 만 이것은 체인이 가능한 클래스를 한 번 초기화하고 참조를 전달해야한다고 생각한 자체 문제점을 가지고 있습니다.

내가 잘못하고있는 부분/다음에 시도 할 수있는 부분에 대한 정보는 훌륭합니다. @ 존 요소에 의해 권장

+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) 
     } 
    } 
}