假设我的协议看起来像这样:
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 :(
答案 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实例是行不通的。