Ctibor Šebák
Ctibor Šebák

Reputation: 133

UIView to UIViewController communication via protocol not working

maybe I am missing something really fundamental here, but after staring at the code for an hour or so, my brain is going trough cycles and I would appreciate a fresh glance at this problem.

I have the following UIView:

import UIKit

protocol DetailViewWillShowUpDelegate {
    func sendDetailOpened(_ openedBool: Bool)
}

class locationXIBController: UIView {

    @IBOutlet weak var loationLabel: UILabel!
    @IBOutlet weak var vsedniOteviraciDobaLabel: UILabel!
    @IBOutlet weak var prijmajiKartyLabel: UILabel!
    @IBOutlet weak var detailViewButtonOutlet: UIButton!
    @IBOutlet weak var backgroundViewButton: UIButton!

    let openedBool = true
    var detailViewWillShowUpDelegate: DetailViewWillShowUpDelegate?

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    @IBAction func vecerkaDetailButtonPressed(_ sender: UIButton) {
        detailViewWillShowUpDelegate?.sendDetailOpened(openedBool)
        print("pressed")
    }

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if let result = detailViewButtonOutlet.hitTest(convert(point, to: detailViewButtonOutlet), with: event) {
            return result
        }
        return backgroundViewButton.hitTest(convert(point, to: backgroundViewButton), with: event)
    }

}

Now the problem is, that when I call/press the vecerkaDetailButtonPressed function I get "pressed" output in the console but the protocol for some reason doesn't go trough.

The other side looks like this (stripped for simplicity):

class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

    let locationXIB = locationXIBController()
    let isVecerkaDetailOpened = false

    override func viewDidLoad() {
       locationXIB.detailViewWillShowUpDelegate = self
    }



extension MapViewController: DetailViewWillShowUpDelegate {
    func sendDetailOpened(_ openedBool: Bool) {
        isVecerkaDetailOpened = openedBool
        print("success")
    }
}

I know the protocol value at the moment of execution is nil. As I said, any help is appreciated, thanks!

Upvotes: 0

Views: 968

Answers (4)

Ctibor Šebák
Ctibor Šebák

Reputation: 133

Answer to the credit of @Paulw11

I finally managed to get it working by communicating like so:

step 1) 1:1 communication via protocol between MKAnnotation and MKAnnotationView

step 2) 1:1 communication via protocol between MKAnnotationView and MapViewController passing the same data

Finally works like a charm, thanks!

Upvotes: 0

Caleb
Caleb

Reputation: 125007

I asked:

So does detailViewWillShowUpDelegate actually point at anything, or is it nil?

And you replied:

I just tried debugging and it is actually nil

So that's the problem... you need to set detailViewWillShowUpDelegate to point to a valid delegate object. This is often done in the .xib file or storyboard, and sometimes people forget to make that connection, so check there if it makes sense. Else you'll just need to get a reference to the delegate at some point before the code in question can run and set it up.

Upvotes: 1

Jacob M. Barnard
Jacob M. Barnard

Reputation: 1367

In addition to the answer of @Duncan C, you might check whether you need super.viewDidLoad() at the top of the viewDidLoad() method in the MapViewController class? Not doing that can lead to quirky things in your app.

Upvotes: 1

Duncan C
Duncan C

Reputation: 131426

First, a couple of naming convention issues:

The name locationXIBController is a bad choice for a UIView object. It is a view object, not a controller object.

Second, class names in Swift should start with an upper-case letter. So LocationXIBView would be a much better name for that view class.

Next, your code

let locationXIB = locationXIBController()

...is wrong. That creates a brand-new instance of your locationXIBController class that you never install in your view hierarchy. You should make that line an IBOutlet:

@IBOutlet weak var locationXIB: locationXIBController!

And then you should control-drag from the locationXIBController in your StoryBoard onto the outlet in your view controller. That will cause Interface Builder to connect the outlet.

Now when you run your program the variable locationXIB will be connected to the locationXIBController view from your storyboard/XIB when it's loaded.

Upvotes: 1

Related Questions