HeMet
HeMet

Reputation: 118

Cannot assign to property in protocol constrained to class - Swift compiler error

I use Xcode 7 beta 6 and I have code like this:

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
}

Compiler complains on assignment view.viewModel = viewModel. I'm understand what ViewForViewModel protocol is not constrained to class by itself, but V type is constrained to UIViewController class. Is it a bug or a feature?

UPD: it even complains about UITableViewCell variable:

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
    }
}

Upvotes: 0

Views: 1355

Answers (3)

Kay
Kay

Reputation: 356

If the Compiler can't infer, that the parameter will always be a reference type, you can always add class to the protocol declaration:

public protocol ViewForViewModel: class {
  typealias ViewModelType
  var viewModel: ViewModelType! { get set }
  func bindToViewModel()
}

Once the protocol is marked up like that, you should be able to assign values to the property even if the object is stored in a constant.

Upvotes: 6

Qbyte
Qbyte

Reputation: 13243

In the first case it should be considered an "unimplemented feature" (that the compiler cannot infer the behavior of a class in this context). So to fix it you have to make the value a var:

func afterViewInstantiated <V : ViewForViewModel where V: UIViewController, V.ViewModelType: AnyObject>(var view : V, viewModel: V.ViewModelType) -> V

In the second case you should provide more information about the error (message) and the types. Where does V come from?

Upvotes: 1

NRitH
NRitH

Reputation: 13893

If the compiler is complaining about the protocol not being able to be used as a non-generic type, delete the typealias in the protocol.

BTW, what is the use case for this?

Upvotes: 0

Related Questions