【问题标题】:Generics inside a delegate or datasource委托或数据源中的泛型
【发布时间】:2014-12-10 08:28:08
【问题描述】:

我正在尝试寻找在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】:

    首先我相信你是有意的

    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
        }
    }
    

    唯一的缺点是必须在协议方法中使用Self 将委托标记为final

    这是一个旧线程,现在您可能已经很清楚这些功能和特性了。希望这对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-03
      • 1970-01-01
      • 1970-01-01
      • 2023-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多