如何使用 属性 初始化 class 并限制为泛型类型和 Swift 中的协议
How to initialize a class with a property that is constrained to a generic type and a protocol in Swift
我正在使用符合协议 Glideable
的 UIViewController
初始化我的 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")
}
}
}
我正在使用符合协议 Glideable
的 UIViewController
初始化我的 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")
}
}
}