解包可选实例属性的最佳位置 - 创建时或调用时?

时间:2017-10-12 23:56:53

标签: swift

如果要在self可用之后创建一个具有初始化的实例属性,通常会将其设为变量并将其声明为选项,如下所示:

var mapView: MGLMapView?

然后当self可用时,您会将其初始化,如下所示:

mapView = MGLMapView(frame: view.bounds)

但是,当您稍后致电mapView时,是否应该使用?!

来致电mapView?.userTrackingMode = .follow mapView!.userTrackingMode = .follow
var mapView: MGLMapView!

或者应该在首次创建属性时将其解包,如下所示:

?

然后放弃使用!或{{1}}。所有这三种可能性都会编译并运行,因此在选择时是否有最佳实践或经验法则?

2 个答案:

答案 0 :(得分:2)

变量应该被声明为隐式展开(使用!),只有当你在init之外指定一个值但在所有其他代码都将访问变量和变量之前肯定会有价值。

典型的例子是视图控制器中的插座。这些值在init之后但在所有其他代码将使用它们之前分配。在这种情况下,awakeFromNibviewDidLoad是初始化的典型位置。由于所有其他代码都可以安全地假设变量具有非零值,因此使用隐式展开的变量是有意义的。

对于“普通”选项(在声明中使用?),你永远不应强制解包这些值,因为变量是可选的全部原因是因为它可能是nil

在这些情况下,请始终使用条件绑定(if let)或可选链接。

在您的示例中,您很可能会在viewDidLoad方法中设置地图视图,因此将其声明为var mapView: MGLMapView!。然后,您可以引用mapView,因为它不是代码中其他任何位置的可选项。只需确保在mapView初始化之前不要尝试访问viewDidLoad

另一种选择是将属性设置为延迟加载的属性。然后,您不需要使用?!声明它。

答案 1 :(得分:2)

如果我们假设在控制器加载时将初始化MapView,那么我们也可以假设所有后续引用都不是nil,并且我们可以隐式解包MapView。

因此,有效的方法是将mapView声明如下

var mapView: MGLMapView!

这被称为隐式展开选项,然后您可以直接引用它,如下所示(前提是mapView不可能在其他地方设置为nil)

mapView.userTrackingMode = .follow

Apple的Swift编程语言中有一节名为“Implicity Unwrapped Optionals”,将详细介绍。

您还可以按照您的指示编写其他方式的代码 - 需要考虑的重要事项是,当打开时,mapView变量是否有可能为nil。如果没有,请使用上述。

您还会注意到,在引用UI组件(标签,文本框等)时,XCode中的界面构建器也会使用隐式展开的变量,这让我相信这是一种合适的方法。