如何使用 属性 初始化 class 并限制为泛型类型和 Swift 中的协议

How to initialize a class with a property that is constrained to a generic type and a protocol in Swift

我正在使用符合协议 GlideableUIViewController 初始化我的 Glide class,如下所示:

class Glide : NSObject, UIGestureRecognizerDelegate, UIScrollViewDelegate {
    private var card: (Glideable & UIViewController)?
    init(parentViewController: UIViewController, configuration: GlideConfiguration, card: Glideable & UIViewController) {}
}

因此,当您创建此 class 的实例时,您传递的 UIViewController 也符合 Glideable 协议。现在我想稍微改变一下,这样如果你有一个 UIViewController 包裹在 UINavigationController 里面,就像这样:

let navCardView = UINavigationController(rootViewController: CardViewController())

然后我用 navCardView 初始化我的 Glide class 这不再只是一个 UIViewController 而是一个 UINavigationController 但我也想确保CardViewController 符合 Glideable 协议。

在使用泛型实现此类架构方面的任何帮助都会有所帮助。我似乎无法理解如何使通用类型受协议约束。

任何想法将不胜感激。谢谢。

我不确定你到底想做什么,但通常你应该使用枚举来表示 swift 中的异构类型。以下是如何使用枚举来处理这两种情况,导航控制器和无导航控制器以及使 class 通用到特定类型的视图控制器:

import SwiftUI
import PlaygroundSupport
import Combine

protocol Glideable { }

typealias GlideableViewController = Glideable & UIViewController

final class Glide<SomeGlidableViewController: GlideableViewController>: NSObject, Glideable {
  private enum Wrapped {
    case viewController(SomeGlidableViewController), navigationContoller(UINavigationController, SomeGlidableViewController)
    var glideViewController: SomeGlidableViewController {
      switch self {
      case let .viewController(viewController): return viewController
      case let .navigationContoller(_, viewController): return viewController
      }
    }
    var navigationController: UINavigationController? {
      guard case let .navigationContoller(navigationContoller, _) = self else { return nil }
      return navigationContoller
    }
  }
  private let wrappedViewController: Wrapped
  init(glideableViewController: SomeGlidableViewController) {
    wrappedViewController = .viewController(glideableViewController)
    super.init()
    commonInit()
  }
  init?(navigationController: UINavigationController) {
    guard let glideableViewController = navigationController.topViewController as? SomeGlidableViewController else {
      return nil
    }
    wrappedViewController = .navigationContoller(navigationController, glideableViewController)
    super.init()
    commonInit()
  }
  private func commonInit() {
    print("This class wraps a VC of type: \(SomeGlidableViewController.self)")
    print("The wrapped VC is \(wrappedViewController.glideViewController)")
    if let navigationController = wrappedViewController.navigationController {
      print("It is wrapped in a navigation controller")
    } else {
      print("It is not wrapped in a navigation controller")
    }
  }
}