我正在尝试将泛型与协议混合在一起,我的xD非常困难
我在Android/Java项目中实现了某些架构,我正在尝试重写它以适应swift/iOS项目.但我发现了这个限制.
ProtocolA
protocol ProtocolA {
}
Run Code Online (Sandbox Code Playgroud)
ProtocolB
protocol ProtocolB : ProtocolA {
}
Run Code Online (Sandbox Code Playgroud)
ImplementProtocolA
class ImplementProtocolA <P : ProtocolA> {
let currentProtocol : P
init(currentProtocol : P) {
self.currentProtocol = currentProtocol
}
}
Run Code Online (Sandbox Code Playgroud)
ImplementProtocolB
class ImplementProtocolB : ImplementProtocolA<ProtocolB> {
}
Run Code Online (Sandbox Code Playgroud)
因此,当我尝试将ProtocolB设置为实现ProtocolA的具体类型时,我收到此错误:
不支持使用'ProtocolB'作为符合协议'ProtocolA'的具体类型
1这种"限制"有什么理由吗?
2是否有任何解决方法可以实现此功能?
3它会在某个时候得到支持吗?
- 更新 -
我认为同一问题的另一个变种是:
查看协议
protocol View {
}
protocol GetUserView : View {
func showProgress()
func hideProgress()
func showError(message:String)
func showUser(userDemo:UserDemo)
}
Run Code Online (Sandbox Code Playgroud)
演示者协议
protocol Presenter {
typealias V : …Run Code Online (Sandbox Code Playgroud) 为什么以下代码会产生错误?
protocol ProtocolA {
var someProperty: ProtocolB { get }
}
protocol ProtocolB {}
class ConformsToB: ProtocolB {}
class SomeClass: ProtocolA { // Type 'SomeClass' does not conform to protocol 'ProtocolA'
var someProperty: ConformsToB
init(someProperty: ConformsToB) {
self.someProperty = someProperty
}
}
Run Code Online (Sandbox Code Playgroud)
这个类似问题的答案是有道理的.但是,在我的示例中,属性是get-only.为什么不能这样做?它是Swift的缺点,还是有一些合理的理由?
我设法让JSON和plist编码和解码都工作,但只能通过直接调用特定对象上的编码/解码函数.
例如:
struct Test: Codable {
var someString: String?
}
let testItem = Test()
testItem.someString = "abc"
let result = try JSONEncoder().encode(testItem)
Run Code Online (Sandbox Code Playgroud)
这很好,没有问题.
但是,我试图获得一个只接受Codable协议一致性类型的函数并保存该对象.
func saveObject(_ object: Encodable, at location: String) {
// Some code
let data = try JSONEncoder().encode(object)
// Some more code
}
Run Code Online (Sandbox Code Playgroud)
这会导致以下错误:
无法使用类型'(Encodable)'的参数列表调用'encode'
看看编码函数的定义,似乎它应该能够接受Encodable,除非Value是一些我不知道的奇怪类型.
open func encode<Value>(_ value: Value) throws -> Data where Value : Encodable
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用Swift 4中的新JSONDecoder/Encoder找到符合swift协议的编码/解码结构数组的最佳方法.
我举了一个例子来说明问题:
首先,我们有一个协议Tag和一些符合这个协议的类型.
protocol Tag: Codable {
var type: String { get }
var value: String { get }
}
struct AuthorTag: Tag {
let type = "author"
let value: String
}
struct GenreTag: Tag {
let type = "genre"
let value: String
}
Run Code Online (Sandbox Code Playgroud)
然后我们有一个Type文章,它有一个标签数组.
struct Article: Codable {
let tags: [Tag]
let title: String
}
Run Code Online (Sandbox Code Playgroud)
最后,我们对文章进行编码或解码
let article = Article(tags: [AuthorTag(value: "Author Tag Value"), GenreTag(value:"Genre Tag Value")], title: "Article Title")
let jsonEncoder = JSONEncoder()
let jsonData = try …Run Code Online (Sandbox Code Playgroud) 扩展不能包含存储属性,但为什么可以在扩展中定义静态存储属性?
我也没有找到任何文档提到扩展中允许静态属性.
extension String {
static let test = "Test"
static var test2 = "Test2"
}
Run Code Online (Sandbox Code Playgroud) 给定没有任何关联类型的协议:
protocol SomeProtocol
{
var someProperty: Int { get }
}
Run Code Online (Sandbox Code Playgroud)
这两个函数在实践中有什么区别(意思不是"一个是通用的而另一个不是")?它们是否生成不同的代码,它们具有不同的运行时特征吗?当一个或多个协议变得非常重要时,这些差异是否会发生变化?(因为编译器可能内联这样的东西)
func generic<T: SomeProtocol>(some: T) -> Int
{
return some.someProperty
}
func nonGeneric(some: SomeProtocol) -> Int
{
return some.someProperty
}
Run Code Online (Sandbox Code Playgroud)
我主要询问编译器的不同之处,我理解两者的语言级含义.基本上,确实nonGeneric意味着一个恒定的代码大小但速度较慢的动态调度,而不是generic每个类型传递的代码大小增加,但是使用快速静态调度?
我正在使用Swinject,一个问题是困扰我.我差不多整整一天都被困在这里.我怀疑这是因为Swift是一种特定类型的语言,但我并不完全确定.
我在这个操场上总结了我的问题
protocol Protocol {}
class Class: Protocol {}
let test: Protocol.Type = Class.self
func printType(confromingClassType: Protocol.Type) {
print(confromingClassType)
}
func printType<Service>(serviceType: Service.Type) {
print(serviceType)
}
print(Class.self) // "Class"
printType(serviceType: Class.self) // "Class"
print(test) // "Class"
printType(confromingClassType: test) // "Class"
printType(serviceType: test) // "note: expected an argument list of type '(serviceType: Service.Type)'"
Run Code Online (Sandbox Code Playgroud)
我尝试了不同的解决方案,如test.self或type(of:test),但它们都不起作用.
所以我想我不能使用作为变量提供的泛型参数来调用函数?
我正在使用协议来定义对默认View协议的覆盖,以在我的应用程序中创建一些模板化视图。它们都将共享CalculationComponent大部分布局的相同视图,但随后将实现使用@ViewBuilder泛型传递的不同按钮/控件。
我遇到的问题是,在定义协议主体时,通用类型在Type 'any View' cannot conform to 'View'. <Content: View>我认为这与上面的部分有直接关系CalculationComponent
计算组件.swift
struct CalculationComponent<Content: View>: View {
@Binding var mainCalculation: String
@Binding var secondaryCalculation: String
@ViewBuilder var content: () -> Content
var body: some View {
// Template UI here
content()
}
}
Run Code Online (Sandbox Code Playgroud)
CalculationView.swift
protocol CalculationView: View {
var mainCalculation: String { get set }
var secondaryCalculation: String { get set}
var body: CalculationComponent<View> { get } // Type 'any View' …Run Code Online (Sandbox Code Playgroud) 我有一个协议,Address它继承自另一个协议Validator,并Address满足Validator扩展中的要求.
还有另一个协议,FromRepresentable它有一个associatedType(ValueWrapper)要求Validator.
现在,如果我尝试使用Addressas associatedType,那么它不会编译.它说,
推断类型'Address'(通过匹配要求'valueForDetail')无效:不符合'Validator'.
这种用法是非法的吗?我们是不是应该能够使用Address的地方Validator,因为所有Addresses都是Validator.
下面是我正在尝试的一段代码.
enum ValidationResult {
case Success
case Failure(String)
}
protocol Validator {
func validate() -> ValidationResult
}
//Address inherits Validator
protocol Address: Validator {
var addressLine1: String {get set}
var city: String {get set}
var country: String {get set}
}
////Fulfill Validator protocol requirements in extension
extension …Run Code Online (Sandbox Code Playgroud) 我正在努力在Swift 4中使用新的强类型KVO语法来观察仅通过协议可见的属性:
import Cocoa
@objc protocol Observable: class {
var bar: Int { get }
}
@objc class Foo: NSObject, Observable {
@objc dynamic var bar = 42
}
let implementation = Foo()
let observable: Observable = implementation
let observation = observable.observe(\.bar, options: .new) { _, change in
guard let newValue = change.newValue else { return }
print(newValue)
}
implementation.bar = 50
Run Code Online (Sandbox Code Playgroud)
error: value of type 'Observable' has no member 'observe'
let observation = observable.observe(\.bar, options: .new) { _, change …Run Code Online (Sandbox Code Playgroud)