Swift 中的强制转换不适用于泛型 UIViewController 子类

Cast in Swift does not work for a generic UIViewController subclass

提问人:Thomas Albert 提问时间:10/21/2023 更新时间:10/22/2023 访问量:41

问:

我有一个子类,泛型本身就是 的子类。ToastViewControllerUIViewControllerToastContentViewUIView

class ToastViewController<ContentViewType: ToastContentView>: UIViewController {
}

class ToastContentView: UIView {
}

我正在使用自定义视图控制器转换,我需要将我的呈现视图控制器从实例转换为。ToastViewControllerUIViewControllerContextTransitioning

if let toastVC = context.viewController(forKey: .to) as? ToastViewController<ToastContentView> {
  Log.debug("OK")
} else {
  Log.debug("NOT OK")
}

我有一些具体的子类,如定义:AlertViewController

final class AlertViewController: ToastViewController<AlertToastView> {
}

final class AlertToastView: ToastContentView {
}

但是之前的强制转换检查总是失败(而我确定视图控制器是 的实例)。AlertViewController

我怎样才能让它工作? 我显然不想将呈现视图控制器转换为具体的子类......

谢谢

Swift UIVievice控制器

评论

0赞 HangarRash 10/22/2023
将“Not OK”消息更改为:。你会得到什么?Log.debug("Not OK: \(context.viewController(forKey: .to)))

答:

0赞 Sweeper 10/22/2023 #1

嗯,是 a ,而不是 ,所以你不能投射。AlertViewControllerToastViewController<AlertToastView>ToastViewController<ToastContentView>

执行此操作的一个简单方法是引入一个协议,其中包含您需要的所有内容。ToastViewController

@MainActor
protocol AnyToastViewController: UIViewController {
    // declare properties/methods you need from ToastViewController here
}

如果需要泛型类型,请向协议添加关联的类型要求:ContentViewType

associatedtype Content: ToastContentView
var contentView: Content { get }

ToastViewController将符合它:

class ToastViewController<ContentViewType: ToastContentView>: UIViewController, AnyToastViewController {

然后你可以改为投射到。any AnyToastViewController

if let toastVC = context.viewController(forKey: .to) as? ToastViewController<ToastContentView> {
    let content = toastVC.contentView
    // and so on...
} else {
    Log.debug("NOT OK")
}

请注意,您只能获取泛型类型的属性,或调用返回 .设置 类型的属性或调用作为参数的方法不是类型安全的。ContentViewTypeContentViewTypeContentViewTypeContentViewType