Swift - Error passing data between protocols / del

2019-08-02 10:56发布

I am developing an application with swift 3.0. Where what I want to do is, from the "MainMapVC" class, which is the view where you have a map with a date slider (see the attached image). I want to move the slider and send that slider position (1,2 or 3) to LeftSideViewController which is the side view (the legend) updating the content depending on the selected date.

View of MainMapVC:

enter image description here

View of MainMapVC with Legend:

enter image description here

Well, and I've come to the point where I have to pass a value between the two view controllers. But problem is that I get the error "fatal error: unexpectedly found nil while unwrapping an optional value". Basically I have a "nil" delegate.

But do not find where the error is, because the definition of the delegate is like "var delegate: MainMapVCDelegate!" And I call it "delegate.moveSliderDates (datePos: Int (roundedValue))" in the "MainMapVC" class.

Does anyone know where I failed in the statement of the delegate?Thanks :)

I attach the code of the two classes so that you see the whole code.

Class MainMapVC (first way):

import UIKit

protocol MainMapVCDelegate: class {

    func moveSliderDates(datePos: Int)

}


class MainMapVC: UIViewController, UISearchBarDelegate, CLLocationManagerDelegate, GMSMapViewDelegate {

//MARK: VARIABLES
weak var delegate: MainMapVCDelegate? = nil


let step: Float = 1
@IBAction func moveSliderDates(_ sender: UISlider) {
    let roundedValue = round(sender.value / step) * step
    sender.value = roundedValue 
    delegate?.moveSliderDates(datePos: Int(roundedValue))      

}

}

The delegate value inside the moveSliderDates function is "nil":

delegate?.moveSliderDates(datePos: Int(roundedValue))

Class LeftSideViewController (first way):

import UIKit

class LeftSideViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, customCellDelegate, MainMapVCDelegate {

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "MainMapVC" {
        let secondViewController = segue.destination as! MainMapVC
        secondViewController.delegate = self
    }
}

func moveSliderDates(datePos: Int){
    print(datePos)
    print("/////////////")
    tableSideLeft.reloadData()
}

not enter inside this function because the delegate of "MainVC" is "nil":

Class MainMapVC (second way):

 let step: Float = 1
 @IBAction func moveSliderDates(_ sender: UISlider) {
    let roundedValue = round(sender.value / step) * step
    sender.value = roundedValue

    let data:[String: Int] = ["data": Int(roundedValue)]
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: data)

}

Class LeftSideViewController (second way):

    func listnerFunction(_ notification: NSNotification) {
    if let data = notification.userInfo?["data"] as? String {
        print(data)
    }



override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(listnerFunction(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil)
}

Never goes into the function listnerFunction

1条回答
够拽才男人
2楼-- · 2019-08-02 11:07

You get the error because you defined your delegate as force unwrapped noy-nil version by this code var delegate: LeftSideDelegate!

Instead, you need to change it like this. You should not create strong reference cycle for delegate.

weak var delegate: LeftSideDelegate? = nil

Then for all your delegate calles, do the wrapped version delegate call

delegate?.changeZindexDelivery()

Other than that, change your line protocol LeftSideDelegate { into protocol LeftSideDelegate : class {

Passing data between view controllers using delegate

First, in the class where you want to pass the data to another view controller, declare protocol in this way

protocol SampleDelegate: class {
    func delegateFunctionCall(data: String)
}

Then, create delegate variable as optional with type weak var. Call delegate method with you want to pass data or trigger action

class SecondViewController: UIViewController {

    weak var delegate: SampleDelegate? = nil

    @IBAction func sendTextBackButton(sender: AnyObject) {
        delegate?.delegateFunctionCall(data: textField.text!)

    }
}

Finally in your view controller that you want to receive action or data, implement the protocol. When you are initiating the second view controller, set it's delegate variable to be the current view controller

class FirstViewController: UIViewController, SampleDelegate {

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showSecondViewController" {
            let secondViewController = segue.destination as! SecondViewController
            secondViewController.delegate = self
        }
    }

    func delegateFunctionCall(data: String) {
        label.text = data
    }
}

Passing data between view controllers using notification

In the destination view controller, register a handler function that is ready to be called. You can add this registration code in view did load

NotificationCenter.default.addObserver(self, selector: #selector(listnerFunction(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil)

func listnerFunction(_ notification: NSNotification) {
    if let data = notification.userInfo?["data"] as? String {
        // do something with your data   
    }
}

Then in another view controller, if you want to pass data, simply call this

let data:[String: String] = ["data": "YourData"]
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: data) 
查看更多
登录 后发表回答