引用符合协议的类

时间:2016-02-21 10:39:59

标签: swift protocols

假设我的协议看起来像这样:

protocol Foo {
    var bar: Bool { get set }
}

现在我的视图控制器符合Foo协议;

class FooViewController: UIViewController, Foo {
    ...
}

在另一堂课中我想做这样的事情:

class FooClass {

    var viewController: UIViewController? // this should conform to Foo protocol

    func setViewController(viewController: UIViewController) {
        if let fooVC = viewController as? Foo {
            // viewController implements Foo protocol
            self.viewController = fooVC
        } else {
            print("ViewController does not conform to Foo protocol")
        }
    }
}

在Objective-C中,我的引用如下:UIViewController<Foo> *vc表示vc是符合Foo协议的类UIViewController的对象。有Swift等价物吗?

编辑:我猜是not possible :(

4 个答案:

答案 0 :(得分:2)

警告:此解决方案可能会非常痛苦。

作为一种解决方法,您可以使用协议合成并最终扩展

在您的示例中,您可能只对<=符合的UIResponder协议方法感兴趣。

UIViewController

但是typealias FooController = protocol<UIResponder, Foo> class FooClass { var viewController: FooController? func setViewController(viewController: FooController) { // viewController implements UIResponder and Foo protocols } } 具有不符​​合任何协议的属性和方法。在这种情况下,您可以制作包含所需方法的协议并扩展UIViewController

UIViewController

答案 1 :(得分:2)

这是解决方案:

let player = AVAudioPlayer()

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    let cell = collectionView.cellForItem(at: indexPath) as! CustomCollectionCell

    print("tapped")

        guard let url = Bundle.main.url(forResource: songsData[indexPath.row].name, withExtension: "mp3") else { return }


        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)
            try AVAudioSession.sharedInstance().setActive(true)

            player = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)

        } catch let error {
            print(error.localizedDescription)
        }

    player.prepareToPlay()
    timerLabel.text = String(player.currentTime)
    slider.alpha = 1
    slider.maximumValue = Float(player.duration)
    slider.currentValue = 0.0

    Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
    player.play()
}

@objc func updateTime(_ timer: Timer) {
    let currentTime = player.currentTime
    var elapsedTime: TimeInterval = currentTime
    let minutes = UInt8(elapsedTime / 60.0)
    elapsedTime -= (TimeInterval(minutes) * 60)
    let seconds = UInt8(elapsedTime)
    elapsedTime -= TimeInterval(seconds)
    let strMinutes = String(format: "%02d", minutes)
    let strSeconds = String(format: "%02d", seconds)
    timerLabel.text = "\(strMinutes):\(strSeconds)"
    timer.invalidate()
    self.slider.currentValue = Float(self.player.currentTime)
    timer.invalidate()
}

答案 2 :(得分:1)

我明白你的意思了。

我认为您不能声明给定类类型的变量符合协议。

但是,如果您只需要检查categories = driver.find_elements_by_css_selector("#categories #category_list li[id^=category] a") result = [{"link": category.get_attribute("href"), "text": category.text} for category in categories] print(result) 是否符合viewController协议(并且您实际上不需要使用Foo中声明的bar属性)那么您可以这样做。

Foo

答案 3 :(得分:0)

您可以定义为viewController:Foo?

根据我们的评论,您应该使用if let fooVC = viewController as? FooViewController。如果你是可选的将viewController绑定到Foo,那么将它分配给UIViewController实例是行不通的。