Reputation: 159
Using storyboard to build UI.
Swift 5.
My setup is as follows :
File 1 - UI
@objc public protocol TestDelegateViewDelegate: class {
**func primaryAction()**
}
class TestDelegateView: UIView {
@IBOutlet private weak var button: UIButton!
weak var delegate: TestDelegateViewDelegate?
@IBAction private func primaryActionPressed(_ sender: UIButton) {
print("print if before delegate executes")
**delegate?.primaryAction()**
print("print if after delegate executes")
}
}
File 2 - ViewController
extension TestDelegateViewController : TestDelegateViewDelegate {
**func primaryAction() {**
self.dismiss(animated: true, completion: nil)
print("print if delegate executes")
}
When I try this code, my code does print all my print statements, yet - I get this error:
Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[Project.TestDelegateView buttonAction]:
unrecognized selector sent to instance 0x11bc0d2a0'
1 - Am I using delegates wrong? I need to keep the IBOutlets and IBActions in the view.
2 - Am I using MVVM wrong perhaps?
3 - What would be the best practices approach to this design pattern?
4 - why would I be getting this error here? it happens after all code runs.
Thanks so much for the help.
Upvotes: 0
Views: 436
Reputation: 159
I found a way around this- How to implement the MVVM design pattern in full. With actions from a UIView . Yet keeping actions mostly in the View controller, with the use of a delegate protocol.
Protocol
@objc public protocol TestDelegateViewDelegate: class {
**func primaryAction()**
}
UIView file
class TestDelegateView: UIView {
@IBOutlet private weak var button: UIButton!
weak var delegate: TestDelegateViewDelegate?
@IBAction private func primaryActionPressed(_ sender: UIButton) {
print("print if before delegate executes")
**delegate?.primaryAction()**
print("print if after delegate executes")
}
init(delegate: TestDelegateViewDelegate) {
self.delegate = delegate
}
}
View Controller
class TestDelegateViewController: UIViewController {
var view: TestDelegateView?
viewDidLoad() {
view = TestDelegateView(delegate: self)
}
}
extension TestDelegateViewController : TestDelegateViewDelegate {
**func primaryAction() {**
self.dismiss(animated: true, completion: nil)
print("print if delegate executes")
}
Upvotes: 0
Reputation: 31016
Something -- presumably a button in your storyboard -- is wired up to a function called buttonAction
. In your code, the IBAction
is called primaryActionPressed
.
The usual way this happens is by renaming code functions while not resetting their storyboard connections to match.
Upvotes: 2