2015-08-29 2 views
0

Я использую Xcode 7 бета-6 и у меня есть следующий код:Невозможно присвоить свойству в протоколе стесненного в классе - Swift ошибок компилятора

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

В первом случае это должно рассматриваться как «нереализованная функция» (что компилятор не может вывести поведение класса в этом контексте). Таким образом, чтобы исправить это вы должны сделать value в var:

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

Во втором случае вы должны предоставить более подробную информацию об ошибке (сообщения) и типов. Откуда берутся V?

+0

Ошибка такая же. Кстати, я обновил второй пример. Кажется, что компилятор просматривает тип протокола, игнорируя только тот тип, который его реализует. – HeMet

+0

@HeMet Вы получаете то же сообщение об ошибке, если вы меняете подпись? Вы пробовали это на детской площадке? – Qbyte

+0

Да, это помогает. Я думаю, что это действительно «нереализованная функция», которая не может сделать вывод о том, кто поддерживает протокол в этом случае. Отмечено как ответ. – HeMet

0

Если компилятор жалуется протокол не в состоянии быть использованы в качестве не универсального типа, удалите typealias в протоколе.

BTW, что такое прецедент для этого?

+0

Нет, он жалуется на аргументы. Я добавил описание ошибки в сообщение. Случай использования - это 'MVVM' для' UIKit'. Он является частью механизма привязки для 'Views' и' ViewModels'. https://github.com/HeMet/MVVMKit – HeMet

+0

Вы когда-нибудь узнавали, как избавиться от ошибки компилятора? – Performat

6

Если компилятор не может сделать вывод, что параметр всегда будет ссылочный тип, вы всегда можете добавить class к декларации протокола:

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

После протокола размечена так, вы должны иметь возможность присваивать значения этому свойству, даже если объект хранится в константе.

Смежные вопросы