1

第一次使用螺栓,我几乎可以理解它们是如何工作的,但是我确信必须有一种更清洁的方式来做我正在做的事情。

在我的示例中,我想下载一个带有类别的 JSON,将它们导入 Core Data,然后下载一个带有成分的 JSON,并将它们也导入。事情需要按此顺序发生,因为我的解析器要求Category对象在解析对象之前已经存在Ingredient

我正在使用BoltsSwift以避免嵌套块,所以我让我的“下载器”和“导入器”返回一个Task.

网络调用(使用 Moya):

static func downloadJSON(target: MoyaAPI) -> BoltsSwift.Task<JSONArray> {
    let taskCompletionSource = TaskCompletionSource<JSONArray>()
    requestJSONArray(target, success: { (jsonArray) in
        taskCompletionSource.set(result: jsonArray)
    }, error: { (error) in
        taskCompletionSource.set(error: error)
    }, failure: { (moyaError) in
        taskCompletionSource.set(error: moyaError)
    })
    return taskCompletionSource.task
}

解析部分(使用 Groot):

func importCategories(from json: JSONArray) -> BoltsSwift.Task<[Category]> {
    let taskCompletionSource = TaskCompletionSource<[Category]>()
    do {
        let categories: [Category] = try objects(fromJSONArray: json, inContext: managedObjectContext)
        taskCompletionSource.set(result: categories)
    } catch {
        taskCompletionSource.set(error: error)
    }
    return taskCompletionSource.task
}

所以后来当我尝试将这 4 个任务实际链接在一起时,我想出了这个:

    NetworkAdapter.downloadJSON(target: .categories).continueOnSuccessWithTask { (json) -> Task<[Category]> in
        return importer.importCategories(from: json)
    }.continueOnSuccessWith { (categories) in
        return NetworkAdapter.downloadJSON(target: .ingredients).continueOnSuccessWithTask(continuation: { (json) -> Task<[Ingredient]> in
            return importer.importIngredients(from: json)
        })
    }

这行得通,但我觉得语法可以更具可读性。有人能解释一下很好地链接这 4 个任务的正确方法是什么吗?

4

1 回答 1

1

在第二次 JSON 下载到顶层之后,您应该能够将嵌套任务拉出,从而使代码更加简洁:

NetworkAdapter.downloadJSON(target: .categories)
  .continueOnSuccessWithTask { (json) in
    return importer.importCategories(from: json)
  }
  .continueOnSuccessWithTask { (_) in
    return NetworkAdapter.downloadJSON(target: .ingredients)
  }
  .continueOnSuccessWithTask { (json) in
    return importer.importIngredients(from: json)
  }

(如果编译器感到困惑,您可能必须在闭包内重新添加返回类型声明。)

如果上述方法对您有用,您可以使用内联闭包进一步精简代码:

NetworkAdapter.downloadJSON(target: .categories)
  .continueOnSuccessWithTask { importer.importCategories(from: $0) }
  .continueOnSuccessWith { NetworkAdapter.downloadJSON(target: .ingredients) }
  .continueOnSuccessWithTask { importer.importIngredients(from: $0) }
于 2017-10-24T11:26:08.640 回答