委托或数据源中的泛型

问题描述 投票:1回答:1

我正在尝试找到在delegatedataSource协议内使用泛型的解决方案。

目前,我已经声明以下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)
}

这导致以下问题:

  1. 正如我已经声明的typealias,我不能再使用@objc和可选标记

  2. 当我将协议声明为非通用类的属性时,出现错误“协议只能用作通用约束,因为它具有自我”

我已经按照如下方式声明了该属性:

class PageViewController: UIViewController, UIScrollViewDelegate {
    var delegate:PageViewControllerDelegate?
}

欢迎任何帮助。

哦,我只是以这种PageViewController情况为例来确定是否可行。我不希望使用其他方法来使用UIPageViewController例如。

ios generics swift protocols
1个回答
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

这是一个旧线程,现在您可能已经很清楚这些功能。希望无论如何都会有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.