【发布时间】:2017-09-12 03:11:46
【问题描述】:
我遇到过几次事情让我感到困惑。我有时会收到类似于以下的错误
无法转换 'Foo!' 类型的值到预期的参数类型 'Foo!
'
我已经搜索过 SO,但还没有真正找到任何解释为什么 Foo!和 Foo! 不一样。
这是一个例子:
// FooViewModel.swift
class FooViewModel: BaseViewModel {
fileprivate var foo: Foo!
fileprivate var bar: Bar = Bar()
init!(model: Foo!) {
super.init()
foo = model
}
override init() {
super.init()
}
func setFooModel(_ model: Foo!) {
self.foo = model
}
func getFooModel() -> Foo! {
return self.foo
}
func getBar() -> Bar {
return bar
}
func getBlah() -> String {
return "Blah"
}
}
这是产生错误的单元测试:
import XCTest
@testable import WooHoo
class FooViewModelTests: XCTestCase {
override func setUp() {
super.setUp()
}
override func tearDown() {
super.tearDown()
}
func testGetBar() {
var foo = Foo()
let vm = FooViewModel()
// The following line generates the error
vm.setFooModel(foo)
XCTAssertEqual("Tell us your Foo for the Bar program.", vm.getBlah())
}
}
我尝试了vm.setFooModel(foo) 的多种变体,但均无济于事,例如vm.setFooModel(foo!) 或将 foo 声明为 var foo: Foo! = Foo()。
编辑: 请注意,上面的代码用于说明我遇到的问题,而不是操作代码。
【问题讨论】:
-
Foo类型声明在哪里?是否有可能在不同的范围内声明了多个Foo? -
我认为你只需要在声明变量
foo时使用Foo!,在其他地方只需使用Foo -
setFooModel和getFooModel方法的意义何在?为什么不直接公开foo属性?getBar方法相同。为什么不简单地将bar属性设置为具有公共读取访问权限? -
将属性声明为在
init方法中初始化的隐式未包装可选项是荒谬的。不要那样做。如果您想要一个可选的,请使用常规可选?,否则使用非可选类型。 -
为什么在
init和Foo参数类型之后使用!?初始化器要么是失败的,要么不是。你不能有一个强制解包的可选返回类型,但你可以有一个非可选的返回类型,你可以在 return 语句中强制解包。参数也是如此,如果您希望参数作为非可选参数,则将该参数声明为非可选参数并在调用点展开。