相关疑难解决方法(0)

将协议和符合类(!)实例作为参数的函数

我试图弄清楚如何定义一个采用以下两个参数的函数:

  1. 协议.
  2. 符合该协议的(引用类型)的实例.

例如,给定

protocol P { }
class C : P { } // Class, conforming to P
class D { }     // Class, not conforming to P
struct E: P { } // Struct, conforming to P
Run Code Online (Sandbox Code Playgroud)

这应该编译:

register(P.self, obj: C()) // (1)
Run Code Online (Sandbox Code Playgroud)

但这些不应该编译:

register(P.self, obj: D()) // (2)  D does not conform to P
register(P.self, obj: E()) // (3)  E is not a class
Run Code Online (Sandbox Code Playgroud)

如果我们放弃第二个参数是类实例的条件,这很容易:

func register<T>(proto: T.Type, obj: T) {
    // ... …
Run Code Online (Sandbox Code Playgroud)

generics swift swift-protocols

6
推荐指数
1
解决办法
674
查看次数

Swift协议继承

我有快速的代码:

protocol ParentProtocol {
    // stuff
}

protocol ChildProtocol: ParentProtocol {
    // additional stuff
}

protocol FooProtocol {
    var variable: ParentProtocol? { get }
}

class Foo:FooProtocol {
    var variable: ChildProtocol?
}
Run Code Online (Sandbox Code Playgroud)

我有编译器错误:

类型'Foo'不符合协议'FooProtocol'

我知道,根据FooProtocol,变量类型必须是ParentProtocol类型.另一方面ChildProtocol继承自ParentProtocol,所以它也是一个ParentProtocol

是否有任何解决方案以这种方式使用协议继承?

swift swift-protocols

6
推荐指数
1
解决办法
4104
查看次数

带有Protocol.Type的Swift泛型

我在Swift中遇到泛型问题(3):

我从服务器获得不同类的不同数据,实现相同的协议,我需要将它们放入具有泛型的类(例如Array)中.

我不知道数据属于哪个类,所以我需要使用协议.所以我有以下结构:

我的协议:

protocol MyProtocol {
    // some protocol stuff
}
Run Code Online (Sandbox Code Playgroud)

一些实现协议的类

class MyProtocolImpl1: MyProtocol{
    // some class stuff
}

class MyProtocolImpl2: MyProtocol {
    // some class stuff
}
....
Run Code Online (Sandbox Code Playgroud)

通用类:

final class MyGenericsClass<T: MyProtocol> {
    // some class stuff
}
Run Code Online (Sandbox Code Playgroud)

现在我想以这种方式使用这个类:

func createClass<T>(model: T.Type) -> MyGenericClass<T> {
    let myClass = MyGenericClass<T>()
    return myClass
}

...
Run Code Online (Sandbox Code Playgroud)

编辑

func getClass() -> MyProtocol.Type {
     return MyProtocolImpl1.self
}

let impl1 = getClass()
let impl2 = MyProtocolImpl2.self

let createdClass = createClass(impl1) //not working …
Run Code Online (Sandbox Code Playgroud)

generics protocols swift

6
推荐指数
1
解决办法
3984
查看次数

要求关联类型在@convention(c)块中可表示

我想有一种通用的方式来做类似Swift 3:

public protocol Callable {
    associatedtype In : CVarArg
    associatedtype Out : CVarArg
}

public struct IntCallable : Callable {
    public typealias In = Int
    public typealias Out = Double

    public typealias FunctionalBlock = @convention(c) (In) -> Out

    public func call(_ block: FunctionalBlock) { /* do stuff */ }
}
Run Code Online (Sandbox Code Playgroud)

所以我希望它看起来像这样:

public protocol Callable {
    associatedtype In : CVarArg
    associatedtype Out : CVarArg
    typealias FunctionalBlock = @convention(c) (In) -> Out
}

public struct IntCallable : Callable {
    public typealias …
Run Code Online (Sandbox Code Playgroud)

swift

6
推荐指数
1
解决办法
155
查看次数

引用类型到 AnyObject 类型的泛型约束的协议

我有一个通用结构声明如下:

struct WeakReference<T: AnyObject> {
    weak var value: T?

    init(value: T?) {
        self.value = value
    }
}
Run Code Online (Sandbox Code Playgroud)

和一个协议:

protocol SomeProtocol: class {

}
Run Code Online (Sandbox Code Playgroud)

但我无法声明 类型的变量WeakReference<SomeProtocol>,编译器抱怨说

“WeakReference”要求是SomeProtocol类类型

有趣的是,在 Swift 中,class是 AnyObject 的类型别名。

我实际上想保存一个数组,WeakReference<SomeProtocol>因为该数组保存强引用。

Swift 中的仅类泛型约束是一个类似的问题,但并没有真正解决这个问题。

我们如何传递SomeProtocolto WeakReference

编辑: 以下场景编译良好,但我们失去了保存弱引用的能力:

struct Reference<T> {
    var value: T?

    init(value: T?) {
        self.value = value
    }
}

var array: [Reference<SomeProtocol>] = []
Run Code Online (Sandbox Code Playgroud)

generics protocols class swift anyobject

6
推荐指数
1
解决办法
1284
查看次数

Swift:嵌套类型擦除

使用Swift 3.0(我可以使用Swift 4.0,如果这对我有帮助......但我认为不会)我想要Erase两级.我要键入什么来擦除具有相关类型的协议,该协议符合协议本身又具有相关类型的协议.所以可以说我想键入擦除嵌套关联类型.

下面的代码是我的代码的极其简化的版本,但它更清楚.所以我真正想要的是这样的:

原始场景 - 未解决

protocol Motor {
    var power: Int { get } 
}

protocol Vehicle {
    associatedType Engine: Motor
    var engine: Engine { get }
}

protocol Transportation {
    associatedType Transport: Vehicle
    var transport: Transport { get }
}
Run Code Online (Sandbox Code Playgroud)

然后我想输入erase Transportation并能够存储一个阵列,AnyTransportation其中任何Vehicle一个可以拥有任何东西Motor.

所以这是一个包含3个协议的场景,其中2个具有(嵌套)关联类型.

我不知道该怎么做.实际上,我甚至不知道如何解决更简单的场景:

简化的场景 - 未解决

我们可以将上面的原始场景简化为我们有2个协议的版本,其中只有1个协议具有关联类型:

protocol Vehicle {
    var speed: Int { get }
}

protocol Transportation {
    associatedtype Transport: Vehicle
    var transport: …
Run Code Online (Sandbox Code Playgroud)

type-erasure ios swift swift3

5
推荐指数
1
解决办法
525
查看次数

Codable 类中的 Codable 变量

鉴于这个类:

class MyClass: Codable {
    var variable : Codable? = nil
}
Run Code Online (Sandbox Code Playgroud)

我得到错误:

类型“MyClass”不符合协议“Decodable”

类型“MyClass”不符合协议“Encodable”

如何将符合 Codable 的通用变量作为 Codable 类中的属性?

swift codable

5
推荐指数
1
解决办法
1135
查看次数

如何约束协议类型的参数以符合Swift 4中的AnyObject?

以一个非常接近在下面看一下:

// Note that this protocol can only be applied to reference types.
protocol Ref: class {
  var zibbles: Int { get set }
}

class Reference: Ref {
  var zibbles: Int = 42
}

// Note very carefully that we are NOT passing an
// instance, but a type itself.
func thwip<T: AnyObject>(into target: T.Type) {

}

// This compiles.
thwip(into: Reference.self)

// This fails to compile.
thwip(into: Ref.self) 
Run Code Online (Sandbox Code Playgroud)

无论情况多么罕见,这是语言应该能够完成的事情.编译器知道Ref必须符合的任何实例AnyObject,因此类型约束thwip应该可以工作,但事实并非如此.

请注意,如果我们 …

swift swift-protocols

5
推荐指数
0
解决办法
104
查看次数

与擦除类型的编码一致性?

我正在尝试编写一个通用函数来解析几种不同的数据类型。

最初这个方法只适用于 Codable 类型,所以它的泛型类型被约束,<T: Codable>一切都很好。不过现在,我正在尝试扩展它以检查返回类型是否为 Codable,并根据该检查相应地解析数据

func parse<T>(from data: Data) throws -> T? {

    switch T.self {
    case is Codable:

        // convince the compiler that T is Codable

        return try? JSONDecoder().decode(T.self, from: data)

    case is [String: Any].Type:

        return try JSONSerialization.jsonObject(with: data, options: []) as? T

    default:
        return nil
    }

}
Run Code Online (Sandbox Code Playgroud)

所以,你可以看到类型检查工作正常,但我被困在得到JSONDecoder().decode(:)接受TCodable类型,一旦我检查了,这是。上面的代码不能编译,有错误

Cannot convert value of type 'T' (generic parameter of instance method 'parse(from:)') to expected argument type 'T' (generic parameter …

generics casting type-erasure swift codable

5
推荐指数
1
解决办法
681
查看次数

是否有关于 Swift 协议关联类型使用 `=` 与 `:` 的信息?

我试图找出是否有关于 Swift 协议associatedtype使用 a=而不是:.

例如。 associatedtype Thing = SomeOtherThingassociatedtype Thing: SomeOtherThing

不要与我typealias Thing = SomeOtherThing始终=相信的(可能让我困惑的)混淆。

我试图抽象包含委托并使用=for associatedtypes 的类的用法,直到遇到一个问题,即该类型的变量由于 而没有公开其属性=,而是需要通常的:,这对我来说是从某种意义上说,但是当我将一个特定更改=为 a时:,它导致一切都崩溃了。我在下面提供了一个示例,其中的想法是能够自由获取/设置委托对象,但或多或​​少有一个协议说它的委托必须是关联类型的类型(带有 )而=不仅仅是正如似乎暗示的那样,“你必须遵守这一点” :

我也不知道我是否迈出了这一步太过分的一步,还有其他更好的方法可以在测试方面表达这一点。这似乎是必需的,因为我不能完全依赖外部对象在测试中按预期工作,而是需要模拟它以故意失败,在某些情况下如此。

import Foundation

// Concrete objects (eg external framework)

protocol ManagerDelegate: AnyObject {
    func managerDidSomething(_ manager: Manager)
}

class Manager {
    weak var delegate: ManagerDelegate?
    func doSomething() {
        delegate?.managerDidSomething(self)
    }
}

// …
Run Code Online (Sandbox Code Playgroud)

generics unit-testing ios associated-types swift

5
推荐指数
1
解决办法
203
查看次数