我正在尝试在delegate
或dataSource
协议中找到使用泛型的解决方案。
现在我宣布了以下protocol
:
@objc protocol PageViewControllerDelegate {
optional func pageViewController(pageViewController: PageViewController, didScrollToViewController viewController:UIViewController)
}
我想要的是这样的通用协议:
@objc protocol PageViewControllerDelegate {
typealias T
optional func pageViewController(pageViewController: PageViewController, didScrollToViewController viewController:T)
}
这会导致以下问题:
当我宣布typealias
时,我不能再使用@objc
和可选标签
当我将协议声明为非泛型类的属性时,我得到错误“协议只能用作通用约束,因为它具有自我”
我已宣布该财产如下:
class PageViewController: UIViewController, UIScrollViewDelegate {
var delegate:PageViewControllerDelegate?
}
欢迎任何帮助。
哦,我只是用这个PageViewController
案例作为例子来判断这是否可行。我不是在寻找另一种使用UIPageViewController
的方法。
答案 0 :(得分:0)
首先,我相信您打算
protocol PageViewControllerDelegate {
associatedtype T: UIViewController
func pageViewController(pageViewController: PageViewController, didScrollToViewController viewController: T)
}
尽管这是旧版本的Swift的旧线程,所以在协议中可能已经使用了typealias
。
看来,Objective-C不支持关联类型,因此无法同时提供可选协议实现和关联类型。但是,您可以利用协议要求有效地创建可选实现,该协议要求通过扩展名获得默认实现,如下所示:
protocol PageViewControllerDelegate {
associatedtype T: UIViewController
func pageViewController(pageViewController: PageViewController, didScrollToViewController viewController: T)
}
extension PageViewControllerDelegate {
// Does nothing on its own. Note that because this method is a requirement of the protocol, dynamic dispatch is used instead of static dispatch
func pageViewController(pageViewController: PageViewController, didScrollToViewController viewController: T) {}
}
class MyClass: PageViewControllerDelegate {
typealias T = UIPageViewController
// No compile-time errors for an effectively optional method
// Custom implementation
//func pageViewController(pageViewController: PageViewController, didScrollToViewController viewController: UIPageViewController) {
//
//}
}
由于声明不明确,因此不允许将变量声明为具有关联类型的协议的类型。这类似于在Swift中不允许简单地将变量声明为Array
类型的方式类似:由于其通用参数,没有单一的Array
类型。关联类型是通用类型的通用参数的协议等效项。有关其他协议功能的进一步说明,请参见here。
您可以尝试以下方法
protocol PageViewControllerDelegate {
associatedtype T: UIViewController
func pageViewController(pageViewController: PageViewController<Self>, didScrollToViewController viewController: T)
}
extension PageViewControllerDelegate {
func pageViewController(pageViewController: PageViewController<Self>, didScrollToViewController viewController: T) {}
}
class PageViewController<Delegate: PageViewControllerDelegate> : UIViewController, UIScrollViewDelegate {
private var delegate: Delegate?
}
final class MyDelegate: PageViewControllerDelegate {
typealias T = UIPageViewController
func pageViewController(pageViewController: PageViewController<MyDelegate>, didScrollToViewController viewController: UIPageViewController) {
// Do something
}
}
唯一的缺点是必须在协议方法中使用final
将委托标记为Self
。
这是一个旧线程,到目前为止,您可能已经很清楚这些功能。希望无论如何都会有帮助。