【问题标题】:Swift generic type property and methodSwift 泛型类型属性和方法
【发布时间】:2016-04-15 19:05:23
【问题描述】:

如何将泛型类型存储在属性中,然后使用该类型属性传入方法?

我有一个工厂,它的方法接收视图控制器类型但返回该视图控制器的实例(容器负责处理)。

public protocol ViewControllerFactoryProtocol {
    func getViewController<T: UIViewController>(type: T.Type) -> UIViewController
}

public class ViewControllerFactory: ViewControllerFactoryProtocol {

private let container: Container

public init(container: Container) {
    self.container = container
}

public func getViewController<T: UIViewController>(type: T.Type) -> UIViewController {
    return self.container.resolve(type)!
}

}

我有这样的财产

var destinationViewController: UIViewController.Type { get }

现在我想做类似的事情:

factory.getViewController(self.destinationViewController)

我将destinationViewController 声明为LoginViewController.self

但它不是那样工作的。奇怪的是,如果我直接这样做,它就可以工作:

factory.getViewController(LoginViewController.self)

有什么帮助吗??谢谢

【问题讨论】:

  • “但它不是那样工作的”:那它是如何工作的呢?或者错误信息是什么?
  • 它只是抛出错误的访问错误。
  • 您是否检查了getViewController 中的self.container.resolve(type) 是否返回nil
  • 是的,它返回 nil...
  • 这就是它崩溃的原因。您正在尝试强制解包 nil 值。那么调试一下为什么返回nil。显然它应该返回一些对象。

标签: ios swift generics types controller


【解决方案1】:

如果没有看到resolve 的代码,就无法说出它崩溃的原因,但我有一个好主意。我怀疑您误解了泛型类型参数和运行时类型参数之间的区别。考虑一下这个简化的代码。

func printType<T>(type: T.Type) {
    print("T is \(T.self)")
    print("type is \(type)")
}

class Super {}
class Sub: Super {}

printType(Super.self) // Super/Super. Good.
printType(Sub.self)   // Sub/Sub. Good.

let type: Super.Type = Sub.self
printType(type) // Super/Sub !!!!!!

为什么最后一种情况是 Super/Sub?因为printType&lt;T&gt; 是在编译时解析的。它只看定义:

func printType<T>(type: T.Type)
let type: Super.Type

printType(type)

为了完成这项工作,我需要一个 T 以使 T.TypeSuper.Type 相同。嗯,那是Super。所以这被编译为:

printType<Super>(type)

现在在运行时,我们看到type 等于Sub.self,这是Super.type 的子类型,所以没关系。我们将其传递给 printType&lt;Super&gt; 并得到您所看到的响应。

所以可能是 resolve 内部的,你在某个地方使用 T,而你想使用 type,并且你试图“解决”UIViewController,这可能返回 nil。

【讨论】:

  • 我可以在调用 self.container.resolve(type) 之前以某种方式获得我需要的确切类型吗?然后通过它而不是“类型”来解析方法
  • 我不确定它是否有帮助,但这里是容器内的 swinjects 解析方法:github.com/Swinject/Swinject/blob/master/Swinject/…
  • 您正在传递类型。 Swinject 不使用它。查看第 133 行。serviceType 的运行时值未使用。仅使用编译时类型。这必须在框架方面进行更改。在 Swift 中以符合 Swinject 想要实现的方式执行此操作可能是不可能的。这个框架看起来很复杂,我个人不推荐它(它混杂了 UIStoryboard,这对于稳定性来说总是一个不好的迹象)。但是,如果您确实想使用它,您肯定需要准确了解它的作用。
  • 在下一个明显的问题之前重申一下:我不知道对 Swinject 是否有任何小的改变会使这项工作。我会打开项目的问题。
猜你喜欢
  • 1970-01-01
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-29
  • 2011-10-08
相关资源
最近更新 更多