什么是Swift相当于声明`typedef SomeClass <someprotocol> MyType`?</someprotocol>

时间:2014-10-20 20:11:17

标签: ios objective-c swift gpuimage

我目前正在一个主要是Objective-C的项目中编写一些Swift代码。在我们的ObjC代码中,我们有一个声明typedef GPUImageOutput<GPUImageInput> MyFilter;的标头。然后我们可以宣布例如@property只能是实现GPUImageOutput的{​​{1}}子类。

(注意:GPUImageInputGPUImageOutput不是由我定义的;它们是GPUImage library的一部分

我们的Swift代码似乎没有认识到这一点,即使标头在我们的桥接头中是#imported。我试图在Swift中复制声明,但这些都不是正确的语法:
GPUImageInput
typealias MyFilter = GPUImageOutput, GPUImageInput

4 个答案:

答案 0 :(得分:4)

你不能像那样声明类型。

我们能做的最好的事情就是这样:

class MyClass {
    private var filter:GPUImageOutput

    init<FilterType:GPUImageOutput where FilterType:GPUImageInput>(filter:FilterType) {
        self.filter = filter
    }

    func setFilter<FilterType:GPUImageOutput where FilterType:GPUImageInput>(filter:FilterType) {
        self.filter = filter
    }

    func someMethod() {
        let output = self.filter
        let input = self.filter as GPUImageInput
        output.someOutputMethod()
        input.someInputMethod()
    }
}

答案 1 :(得分:3)

在Swift 4中,您可以使用新的&amp; sign(下面是确认UIViewController和UITableViewDataSource的参数示例:

func foo(vc: UIViewController & UITableViewDataSource) {
    // access UIViewController property
    let view = vc.view
    // call UITableViewDataSource method
    let sections = vc.numberOfSectionsInTableView?(tableView)
}

答案 2 :(得分:1)

在Swift中,类似下面的内容应该可以完成你的任务,但它与它的ObjC对应物不同:

typealias GPUImageOutput = UIImage
@objc protocol GPUImageInput {
    func lotsOfInput()
}

class GPUImageOutputWithInput: GPUImageOutput, GPUImageInput
{
    func lotsOfInput() {
        println("lotsOfInput")
    }
}

// ...

var someGpuImage = GPUImageOutput()
var specificGpuImage = GPUImageOutputWithInput()

for image in [someGpuImage, specificGpuImage] {
    if let specificImage = image as? GPUImageInput {
        specificImage.lotsOfInput()
    } else {
        println("the less specific type")
    }
}

更新:现在我明白你在哪里/为何拥有这些类型...

GPUImage似乎有一个快速的例子可以做到你想要的,尽可能快速。

请参阅here

class FilterOperation<FilterClass: GPUImageOutput where FilterClass: GPUImageInput>: FilterOperationInterface {
...

type constraint syntax也可以应用于函数,并使用where clause,这可能与您直接在Swift中获得的效果一样好。

我试图了解如何移植这个有点常见的objc转义,我越是意识到它是最快速的方式。一旦我在GPUImage本身看到了这个例子,我确信它至少是你的答案。 : - )

更新2:所以,除了上面链接到使用Swift的特定GPUImage示例之外,我越来越多地考虑这个问题,要么使用where子句来保护setter函数,要么使用可计算属性过滤set功能似乎是唯一的出路。

我提出了这个策略:

import Foundation

@objc protocol SpecialProtocol {
    func special()
}

class MyClass {}

class MyClassPlus: MyClass, SpecialProtocol {
    func special() {
        println("I'm special")
    }
}

class MyContainer {
    private var i: MyClass?

    var test: MyClass? {
        get {
            return self.i
        }
        set (newValue) {
            if newValue is SpecialProtocol {
               self.i = newValue
            }
        }
    }
}

var container = MyContainer()

println("should be nil: \(container.test)")

container.test = MyClass()
println("should still be nil: \(container.test)")

container.test = MyClassPlus()
println("should be set: \(container.test)")

(container.test as? MyClassPlus)?.special()

输出:

should be nil: nil
should still be nil: nil
should be set: Optional(main.MyClassPlus)
I'm special

(或者,您也可以使用precondition(newValue is SpecialProtocol, "newValue did not conform to SpecialProtocol")代替is检查,但如果案例不符合,assert()就会导致应用程序崩溃。取决于根据你的需要。)

@ rintaro的答案是一个很好的答案,并且是使用where子句作为后卫的一个很好的例子(兼具良好的功能和Swift-ly)。但是,我只是讨厌在可计算属性存在时编写setFoo()函数。然后,即使使用可计算属性也有代码味道,因为我们似乎无法将通用类型约束应用于set,并且必须在线进行协议一致性测试。

答案 3 :(得分:-3)

您可以使用typealias关键字。以下是如何做到这一点:

typealias MyNewType = MyExistingType

MyExistingType是协议还是函数或枚举无关紧要。它只需要某种类型。最好的部分是你可以对它应用访问控制。你可以说

private typealias MyNewType = MyExistingType

这使得MyNewType只能访问在。

中定义的上下文