0

我正在用 Swift 为 iOS 制作一个应用程序,并且我试图将我的 API 调用逻辑保留在我的 ViewControllers 之外。我按照本教程进行了 1 个 API 调用,我将在下面进行描述。

我正在创建 ViewController 将实现的协议“APIControllerProtocol”,然后我正在创建一个 APIController 类,该类将包含一个名为“delegate”的属性来保存 APIControllerProtocol 类型的实例。该协议被简单地定义为

protocol APIControllerProtocol {
    func didReceiveAPIResults(result: SwiftyJSON.JSON)
}

并且 ViewController 会实现在 API 调用返回 JSON 数据后调用的 didReceiveAPIResults 函数。ViewController 将包含 APIController 的一个实例,以调用一个调用 API 的函数。

此时我想让更多的 ViewController 执行 API 调用,如果我只需要对每个 ViewController 进行 1 个 API 调用,我可以在 APIController 中添加另一个函数,我可以让新的 ViewController 使用相同的协议。但是,如果存在需要进行 2 次或更多 API 调用的 ViewController,则此逻辑是有缺陷的,因为

  1. 我不能以两种不同的方式在 ViewController 中调用 didReceiveAPIResults,
  2. 我不认为向 APIController 类添加多个“委托”属性来保存不同类型的协议是要走的路。

  3. 在一个协议中定义多个函数意味着我必须在 ViewControllers 中实现所有这些函数,而这些函数只需要进行 1 个 API 调用。

我解决这个问题的想法是

  1. 为每个 ViewController 创建一个 APIController 类和 APIControllerProtocol

  2. 在 APIControllerProtocol 中使用可选函数,因此并非每个 ViewController 都必须实现所有函数(我不知道这将如何真正起作用)

任何其他见解将不胜感激。

4

3 回答 3

0

您对“API”一词的使用令人困惑。听起来您的意思是服务器请求,所以这就是我要称呼它的意思。

我建议使用完成块/闭包设计,而不是基于协议的设计。

使您对网络请求类的调用采用完成闭包,并在服务器请求完成后调用该完成闭包。

您可以编写网络请求类来维护请求列表和每个待处理请求的完成闭包,并在每个请求完成或失败时调用该闭包。

于 2015-04-22T14:45:59.167 回答
0

在一个协议中定义多个函数意味着我必须在 ViewControllers 中实现所有这些函数,而这些函数只需要进行 1 个 API 调用。

这是不正确的。创建可选函数,您可能会得到答案。

@objc protocol APIControllerProtocol {
    func didReceiveAPIResults(result: SwiftyJSON.JSON)
    optional func someAwesomeMethod()
}

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html

可选协议要求

您可以为协议定义可选要求,这些要求不必由符合协议的类型实现。可选要求以可选修饰符作为前缀,作为协议定义的一部分。

可以使用可选链接调用可选协议要求,以说明该要求未由符合协议的类型实现的可能性。有关可选链接的信息,请参阅可选链接。

您可以通过在调用需求名称后写一个问号来检查可选需求的实现,例如 someOptionalMethod?(someArgument)。可选的属性要求和返回值的可选方法要求,在访问或调用时总是会返回适当类型的可选值,以反映可选要求可能尚未实现的事实。

于 2015-04-22T14:32:07.520 回答
0

您基于逻辑的教程对我来说看起来不太好。它做什么,它实现了一个标准的委托模式,调整到最大。DetailsViewController 有一个 APIViewController 实例,它将自己作为委托分配给该实例 - 非常标准。但随后 DetailsViewController 调用该 APIViewController 实例上的方法以触发委托方法,这些委托方法在 DetailsViewController 中实现。这对我来说太过分了。

更明智的模式是创建一个单例(共享实例)对象,该对象将处理您的 API 调用,并且任何视图控制器都可以访问它。在那里,您可以实现带有参数的方法,其中之一是闭包,当您的请求完成将结果传递给视图控制器时可以调用该闭包。

因此,在您的视图控制器中,您可以这样调用:

 APIController.sharedInstance.doSomethingWith(someParameter, completion: { (result) -> Void in
    // Do something with the result
 })

你的 APIController 会像这样实现

func doSomethingWith(param: String, completion: (AnyObject) -> Void) {
  // do your data fetching here...
  // pass the result to the closure when the data is retrieved
  completion(result)
}
于 2017-03-23T00:06:01.653 回答