使用协议

时间:2015-04-22 14:28:17

标签: ios swift swift-protocols

我正在为Swift中的iOS制作应用程序,我正在尝试将我的API调用逻辑保留在ViewControllers之外。我跟着this tutorial进行了1次API调用,我将在下面介绍。

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

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

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

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

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

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

  4. 我解决这个问题的想法是

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

    2. 在APIControllerProtocol中使用可选功能,因此不是每个ViewController都必须实现所有功能(我不知道这是如何工作的)

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

3 个答案:

答案 0 :(得分: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)。可选属性   要求,以及返回值的可选方法要求,   将始终返回适当类型的可选值   被访问或调用,以反映可选的事实   要求可能尚未实施。

答案 1 :(得分:0)

您使用的术语" API"令人困惑。听起来你的意思是服务器请求,这就是我要称之为的内容。

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

调用您的网络请求类进行完成关闭,并在服务器请求完成后调用该完成关闭。

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

答案 2 :(得分: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)
}