Rah*_*iya 11 generics ios swift swift-protocols
我正在开发一个Restofire库,我想在其中保留一个配置对象.我想在配置对象中有一个ResponseSerializer,但事情是ResponseSerializer是一个通用的.
public struct Configuration<M> {
/// The Default `Configuration`.
static let defaultConfiguration = Configuration<AnyObject>()
/// The base URL. `nil` by default.
public var baseURL: String!
/// The `ResponseSerializer`
public var responseSerializer: ResponseSerializer<M, NSError> = AlamofireUtils.JSONResponseSerializer()
/// The logging, if enabled prints the debug textual representation of the
/// request when the response is recieved. `false` by default.
public var logging: Bool = false
}
Run Code Online (Sandbox Code Playgroud)
我用baseUrl设置了defaultConfiguration Configuration.defaultConfiguration.baseUrl = "http://httpbin.org/"
我有一个带有associatedType要求的协议,它使用defaultConfiguration作为默认实现.但我需要将通用AnyObject更改为associatedType模型,以便配置对象的responseSerializer返回类型Model.
public protocol Configurable {
associatedtype Model
/// The Restofire configuration.
var configuration: Configuration<Model> { get }
}
public extension Configurable {
/// `Restofire.defaultConfiguration`
// Cannot convert return expression of Configuration<AnyObject> to return type Configuration <Self.Model>
public var configuration: Configuration<Model> {
return Restofire.defaultConfiguration
}
}
Run Code Online (Sandbox Code Playgroud)
我收到了错误 Cannot convert return expression of Configuration<AnyObject> to return type Configuration <Self.Model>
我怎样才能使用Model而不是AnyObject?
我还有一个继承自Configurable的协议Requestable
public protocol Requestable: Configurable {
/// The type of object returned in response.
associatedtype Model
/// The base URL.
var baseURL: String { get }
/// The path relative to base URL.
var path: String { get }
/// The request parameters.
var parameters: AnyObject? { get }
/// The logging.
var logging: Bool { get }
/// The Response Serializer
var responseSerializer: ResponseSerializer<Model, NSError> { get }
}
// MARK: - Default Implementation
public extension Requestable {
/// `configuration.BaseURL`
public var baseURL: String {
return configuration.baseURL
}
/// `nil`
public var parameters: AnyObject? {
return nil
}
/// `configuration.logging`
public var logging: Bool {
return configuration.logging
}
/// `configuration.responseSerializer`
var responseSerializer: ResponseSerializer<Model, NSError> {
return configuration.responseSerializer
}
}
Run Code Online (Sandbox Code Playgroud)
RealCode at https://github.com/Restofire/Restofire/compare/Add/DefaultResponseSerializer
我可以直接在下面做,但用户将无法使用配置对象进行设置.
// MARK: - Default Implementation
public extension Requestable {
/// `configuration.responseSerializer`
var responseSerializer: ResponseSerializer<Model, NSError> {
return AlamofireUtils.JSONResponseSerializer()
}
}
Run Code Online (Sandbox Code Playgroud)
还有其他方法吗?
你想做的事是不可能的。这是因为 Swift 中的强类型安全系统。
看起来您想将 限制configuration为关联的 type Model,但您还想提供默认配置。这里的问题是您的默认配置不能保证其泛型类型与Model.
Swift 类型系统不会让你<AnyObject>作为 type传递<Model>,因为它无法确保对象实际上是该类型Model。
当您使某些内容符合Configurable并声明 的类型时Model,您是在说:“我的配置必须使用我给出的类型。” 不能defaultConfiguration保证这一点,所以不能以这种方式使用。
responseSerializer通过查看您的代码,您可以使用它来确定要使用的类型。但是,如果您使用不同的Configurable对象,它们都需要不同的responseSerializers,因此它们不能都使用默认配置。
我花了很多时间思考这个问题,但我没有找到任何解决办法。你将不得不以某种方式改变你的设计。
如果你将其转移responseSerializer到协议上Configurable,那么你就可以使其成为Configuration非通用的。在这种情况下,您将能够responseSerializer在 上的协议扩展中创建Configurable. 如果您需要使用responseSerializer独立于对象的配置Configurable,那么您必须在responseSerializer<AnyObject, NSError>使用它的任何地方创建一个。我不熟悉您的图书馆的整个设计和意图,所以我不确定这是否适合您想要实现的目标。
我可以肯定地告诉您的一件事是,您的设计必须更改才能使用defaultConfiguration.
| 归档时间: |
|
| 查看次数: |
480 次 |
| 最近记录: |