我使用的是Xcode 7 beta 6,我的代码如下:
public protocol ViewForViewModel {
typealias ViewModelType
var viewModel: ViewModelType! { get set }
func bindToViewModel()
}
func afterViewInstantiated <V : ViewForViewModel where V: UIViewController, V.ViewModelType: AnyObject>(view : V, viewModel: V.ViewModelType) -> V {
//Cannot assign to property: 'view' is a 'let' constant
view.viewModel = viewModel // error here
VMTracker.append(viewModel, view: view)
return view
}
编译器在分配view.viewModel = viewModel
时抱怨。
我理解ViewForViewModel
协议本身并不局限于类,但V
类型被约束为UIViewController
类。这是一个错误还是一个功能?
UPD:它甚至抱怨UITableViewCell
变量:
func registerBinding<V: BindableCellView where V: UITableViewCell>(viewType: V.Type) {
let typeName = nameOfType(V.ViewModelType.self)
bindings[typeName] = { [unowned self] viewModel, indexPath in
let view = self.tableView.dequeueReusableCellWithIdentifier(V.CellIdentifier, forIndexPath: indexPath) as! V
//Cannot assign to 'viewModel' because 'view' is a 'let' constant
//However view is UITableViewCell that support ViewForViewModel protocol
view.viewModel = viewModel as! V.ViewModelType
self.onWillBind?(view, indexPath)
view.bindToViewModel()
self.onDidBind?(view, indexPath)
return view
}
}
答案 0 :(得分:6)
如果编译器无法推断,该参数将始终是引用类型,您始终可以将class
添加到协议声明中:
public protocol ViewForViewModel: class {
typealias ViewModelType
var viewModel: ViewModelType! { get set }
func bindToViewModel()
}
一旦协议被标记为这样,即使对象存储在常量中,您也应该能够为属性赋值。
答案 1 :(得分:1)
在第一种情况下,它应被视为“未实现的功能”(编译器无法在此上下文中推断类的行为)。因此,要解决此问题,您必须将value
设为var
:
func afterViewInstantiated <V : ViewForViewModel where V: UIViewController, V.ViewModelType: AnyObject>(var view : V, viewModel: V.ViewModelType) -> V
在第二种情况下,您应该提供有关错误(消息)和类型的更多信息。 V
来自哪里?
答案 2 :(得分:0)
如果编译器抱怨该协议无法用作非泛型类型,请删除协议中的typealias
。