使用协议实现多个 API 调用(服务器请求)
Implementing multiple API calls (server requests) using protocols
我正在 Swift 中为 iOS 开发一个应用程序,我试图将我的 API 调用逻辑放在 ViewController 之外。我跟随 this tutorial 进行了 1 次 API 调用,我将在下面进行描述。
我正在创建一个 ViewController 将实施的协议 'APIControllerProtocol',然后我正在创建一个 API控制器 class,它将包含一个 属性 调用 'delegate' 来保存 APIControllerProtocol 类型的实例。协议简单定义为
protocol APIControllerProtocol {
func didReceiveAPIResults(result: SwiftyJSON.JSON)
}
而ViewController会实现didReceiveAPIResults函数,在API调用returnsJSON数据后调用。 ViewController 将包含 APIController 的一个实例以及调用一个函数,该函数调用 API.
此时我希望有更多的 ViewController 执行 API 调用,如果我只需要为每个 ViewController 调用 1 API,我可以只需向 APIController 添加另一个功能,我就可以让新的 ViewController 使用相同的协议。但是,如果 ViewController 需要进行 2 次或更多次 API 调用,则此逻辑存在缺陷,因为
- 我无法以两种不同的方式调用 didReceiveAPIViewController 结果,
我不认为向 APIController class 添加多个 'delegate' 属性来保存不同类型的协议是可行的方法。
在协议中定义多个函数意味着我必须在 ViewController 中实现所有这些函数,只需要进行 1 API 调用。
我解决这个问题的思路是
为每个 ViewController
创建一个 APIController class 和 APIControllerProtocol
在 APIControllerProtocol 中使用可选函数,因此并非每个 ViewController 都必须实现所有函数(我不知道这将如何工作)
任何其他见解将不胜感激。
Defining multiple functions in a protocol would mean I would have to
implement all of these functions in ViewControllers that only need to
make 1 API call.
这是不正确的。创建可选函数,您可能已经有了答案。
@objc protocol APIControllerProtocol {
func didReceiveAPIResults(result: SwiftyJSON.JSON)
optional func someAwesomeMethod()
}
Optional Protocol Requirements
You can define optional requirements for protocols, These requirements
do not have to be implemented by types that conform to the protocol.
Optional requirements are prefixed by the optional modifier as part of
the protocol’s definition.
An optional protocol requirement can be called with optional chaining,
to account for the possibility that the requirement was not
implemented by a type that conforms to the protocol. For information
on optional chaining, see Optional Chaining.
You check for an implementation of an optional requirement by writing
a question mark after the name of the requirement when it is called,
such as someOptionalMethod?(someArgument). Optional property
requirements, and optional method requirements that return a value,
will always return an optional value of the appropriate type when they
are accessed or called, to reflect the fact that the optional
requirement may not have been implemented.
您对术语 "API" 的使用令人困惑。听起来你的意思是服务器请求,所以我要这样称呼它。
我建议使用完成 block/closure 设计而不是基于协议的设计。
调用您的网络请求class进行完成关闭,并在服务器请求完成后调用该完成关闭。
您可以编写网络请求 class 来维护请求列表和每个待处理请求的完成闭包,并在每个请求完成或失败时调用闭包。
你的逻辑所依据的教程对我来说并不合适。它所做的是,它实现了一个最大程度调整的标准委托模式。 DetailsViewController 有一个 APIViewController 实例,它将自己指定为委托 - 非常标准。但随后 DetailsViewController 调用 APIViewController 实例上的方法,以便触发委托方法,这些方法在 DetailsViewController 中实现。这对我来说太绕圈子了。
一个更明智的模式是创建一个单例(共享实例)对象来处理你的 API 调用并且任何视图控制器都可以访问它。在那里你可以实现你的方法来获取你的参数,其中之一是一个闭包,当你的请求完成将结果传递给视图控制器时可以调用它。
所以在你的视图控制器中你会这样调用:
APIController.sharedInstance.doSomethingWith(someParameter, completion: { (result) -> Void in
// Do something with the result
})
你的API控制器会像这样实现这个
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)
}
我正在 Swift 中为 iOS 开发一个应用程序,我试图将我的 API 调用逻辑放在 ViewController 之外。我跟随 this tutorial 进行了 1 次 API 调用,我将在下面进行描述。
我正在创建一个 ViewController 将实施的协议 'APIControllerProtocol',然后我正在创建一个 API控制器 class,它将包含一个 属性 调用 'delegate' 来保存 APIControllerProtocol 类型的实例。协议简单定义为
protocol APIControllerProtocol {
func didReceiveAPIResults(result: SwiftyJSON.JSON)
}
而ViewController会实现didReceiveAPIResults函数,在API调用returnsJSON数据后调用。 ViewController 将包含 APIController 的一个实例以及调用一个函数,该函数调用 API.
此时我希望有更多的 ViewController 执行 API 调用,如果我只需要为每个 ViewController 调用 1 API,我可以只需向 APIController 添加另一个功能,我就可以让新的 ViewController 使用相同的协议。但是,如果 ViewController 需要进行 2 次或更多次 API 调用,则此逻辑存在缺陷,因为
- 我无法以两种不同的方式调用 didReceiveAPIViewController 结果,
我不认为向 APIController class 添加多个 'delegate' 属性来保存不同类型的协议是可行的方法。
在协议中定义多个函数意味着我必须在 ViewController 中实现所有这些函数,只需要进行 1 API 调用。
我解决这个问题的思路是
为每个 ViewController
创建一个 APIController class 和 APIControllerProtocol
在 APIControllerProtocol 中使用可选函数,因此并非每个 ViewController 都必须实现所有函数(我不知道这将如何工作)
任何其他见解将不胜感激。
Defining multiple functions in a protocol would mean I would have to implement all of these functions in ViewControllers that only need to make 1 API call.
这是不正确的。创建可选函数,您可能已经有了答案。
@objc protocol APIControllerProtocol {
func didReceiveAPIResults(result: SwiftyJSON.JSON)
optional func someAwesomeMethod()
}
Optional Protocol Requirements
You can define optional requirements for protocols, These requirements do not have to be implemented by types that conform to the protocol. Optional requirements are prefixed by the optional modifier as part of the protocol’s definition.
An optional protocol requirement can be called with optional chaining, to account for the possibility that the requirement was not implemented by a type that conforms to the protocol. For information on optional chaining, see Optional Chaining.
You check for an implementation of an optional requirement by writing a question mark after the name of the requirement when it is called, such as someOptionalMethod?(someArgument). Optional property requirements, and optional method requirements that return a value, will always return an optional value of the appropriate type when they are accessed or called, to reflect the fact that the optional requirement may not have been implemented.
您对术语 "API" 的使用令人困惑。听起来你的意思是服务器请求,所以我要这样称呼它。
我建议使用完成 block/closure 设计而不是基于协议的设计。
调用您的网络请求class进行完成关闭,并在服务器请求完成后调用该完成关闭。
您可以编写网络请求 class 来维护请求列表和每个待处理请求的完成闭包,并在每个请求完成或失败时调用闭包。
你的逻辑所依据的教程对我来说并不合适。它所做的是,它实现了一个最大程度调整的标准委托模式。 DetailsViewController 有一个 APIViewController 实例,它将自己指定为委托 - 非常标准。但随后 DetailsViewController 调用 APIViewController 实例上的方法,以便触发委托方法,这些方法在 DetailsViewController 中实现。这对我来说太绕圈子了。
一个更明智的模式是创建一个单例(共享实例)对象来处理你的 API 调用并且任何视图控制器都可以访问它。在那里你可以实现你的方法来获取你的参数,其中之一是一个闭包,当你的请求完成将结果传递给视图控制器时可以调用它。
所以在你的视图控制器中你会这样调用:
APIController.sharedInstance.doSomethingWith(someParameter, completion: { (result) -> Void in
// Do something with the result
})
你的API控制器会像这样实现这个
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)
}