Swift - 在协议/委托之间传递数据时出错(找到无)

时间:2017-07-10 10:53:46

标签: swift null delegates protocols

我正在使用swift 3.0开发一个应用程序。我想要做的是,来自" MainMapVC" class,这是一个带有日期滑块的地图的视图(参见附图)。我想移动滑块并将滑块位置(1,2或3)发送到LeftSideViewController,这是侧视图(图例),根据所选日期更新内容。

MainMapVC视图:

enter image description here

使用图例的MainMapVC视图:

enter image description here

好吧,我已经到了必须在两个视图控制器之间传递值的地步。但问题是我得到了错误"致命错误:在展开可选值"时意外地发现了nil。基本上我有一个" nil"委派。

但是找不到错误的位置,因为委托的定义就像" var delegate:MainMapVCDelegate!"我称之为" delegate.moveSliderDates(datePos:Int(roundedValue))"在" MainMapVC"类。

是否有人知道代表声明中我失败的地方?谢谢:)

我附上两个类的代码,以便您看到整个代码。

类MainMapVC(第一种方式):

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))      

}

}

moveSliderDates函数中的委托值为" nil":

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

类LeftSideViewController(第一种方式):

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()
}

不能进入此功能,因为" MainVC"的代表是" nil":

类MainMapVC(第二种方式):

 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)

}

类LeftSideViewController(第二种方式):

    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)
}

永远不会进入功能listnerFunction

1 个答案:

答案 0 :(得分:2)

您收到错误是因为您通过此代码var delegate: LeftSideDelegate!

将您的委托定义为强制解包noy-nil版本

相反,你需要像这样改变它。您不应该为委托创建强大的参考周期。

weak var delegate: LeftSideDelegate? = nil

然后,对于所有委托的calles,执行包装版本委托调用

delegate?.changeZindexDelivery()

除此之外,请将您的专线protocol LeftSideDelegate {更改为protocol LeftSideDelegate : class {

使用委托

在视图控制器之间传递数据

首先,在要将数据传递给另一个视图控制器的类中,以这种方式声明协议

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

然后,使用类型weak var创建委托变量作为可选项。调用委托方法,您想要传递数据或触发操作

class SecondViewController: UIViewController {

    weak var delegate: SampleDelegate? = nil

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

    }
}

最后,在您希望接收操作或数据的视图控制器中,实现协议。当您启动第二个视图控制器时,将其委托变量设置为当前视图控制器

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
    }
}

使用通知

在视图控制器之间传递数据

在目标视图控制器中,注册准备调用的处理函数。您可以在视图中添加此注册码

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   
    }
}

然后在另一个视图控制器中,如果要传递数据,只需调用此

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