2016-10-29 95 views
0

我想通过学习教程(link)和来了解MVVM模式我无法获得我添加到UIButton中的操作来工作(I'使用Swift 3.0)。我已经尝试了几个小时的调试,研究了这个线程(@selector in swift)和其他人,而且我仍然陷入困境。当我点击按钮时,根本没有任何反应。我用选择器尝试了各种语法选项,我认为你在下面看到的是正确的。我认为我使用的协议可能会导致问题,但鉴于我对协议的有限经验,我可能完全错误。在UIButton上的操作不起作用

我会把所有的代码放在这里,以防有人想把它放到Xcode中。这里所讨论的行动是在我UIViewController,我添加到showGreetingButton

class GreetingViewController : UIViewController { 
    let showGreetingButton = UIButton() 
    @IBOutlet weak var greetingLabel: UILabel! 

    var viewModel: GreetingViewModelProtocol! { 
    didSet { 
     self.viewModel.greetingDidChange = { [unowned self] viewModel in 
     self.greetingLabel.text = viewModel.greeting 
     } 
    } 
    } 

    required init?(coder aDecoder: NSCoder) { 
    super.init(coder: aDecoder) 
    } 

    override func viewDidLoad() { 
    super.viewDidLoad() 
    showGreetingButton.backgroundColor = UIColor.red 
    showGreetingButton.tintColor = UIColor.black 
    showGreetingButton.setTitle("Show Greeting", for: .normal) 

    // I add the action here: 
    showGreetingButton.addTarget(self.viewModel, action: #selector(GreetingViewModel.showGreeting), for: .touchUpInside) 

    showGreetingButton.translatesAutoresizingMaskIntoConstraints = false  
    view.addSubview(showGreetingButton) 
    let buttonTop = NSLayoutConstraint(item: showGreetingButton, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.greaterThanOrEqual, toItem: view, attribute: NSLayoutAttribute.topMargin, multiplier: 1.0, constant: 20) 
    let buttonLeading = NSLayoutConstraint(item: showGreetingButton, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.leadingMargin, multiplier: 1.0, constant: 0.0) 
    showGreetingButton.contentEdgeInsets = UIEdgeInsetsMake(2, 2, 2, 2) 
    NSLayoutConstraint.activate([buttonTop, buttonLeading]) 

    let model = Person(firstName: "David", lastName: "Blaine") 

    let viewModel = GreetingViewModel(person: model) 

    self.viewModel = viewModel 
    } 
} 

我的视图模型被称为GreetingViewModel其采用的协议:

protocol GreetingViewModelProtocol: class {  
    var greeting: String? { get } 
    var greetingDidChange: ((GreetingViewModelProtocol) ->())? { get set } 
    init(person: Person) 
    func showGreeting() 
} 

class GreetingViewModel : GreetingViewModelProtocol { 
    let person: Person 
    var greeting: String? { 
    didSet { 
     self.greetingDidChange?(self) 
    } 
    } 

    var greetingDidChange: ((GreetingViewModelProtocol) ->())? 

    required init(person: Person) { 
    self.person = person 
    } 

    @objc func showGreeting() { 
    self.greeting = "Hello" + " " + self.person.firstName + " " + self.person.lastName 
    } 
} 

我的简单模式是:

struct Person { 
    let firstName: String 
    let lastName: String 
} 

任何帮助将真的,真的很感激。

回答

0

移动这些行您设置按钮的目标之前:

let viewModel = GreetingViewModel(person: model) 
self.viewModel = viewModel 

现在要添加self.viewModel为目标,但self.viewModelnil

+0

我也不得不搬到'让模型=人(名字:“大卫”,姓氏:“布莱恩”)与这两行,但它的工作!谢谢! – Jim

+0

@Vinodh,@ beyoulf的回答在你编辑它之前是更好的,因为它明确表示重要的是这些行在showGreetingButton.addTarget(self.viewModel,action:#selector(GreetingViewModel.showGreeting)之前,用于: .touchUpInside)'。你的编辑不太清楚。 – Jim

+0

将替换旧的 – Vinodh