【问题标题】:Swift navigate back from view2 to view1Swift 从 view2 导航回 view1
【发布时间】:2018-05-01 18:14:12
【问题描述】:

我有 View1,其中按钮有标题,我通过传递按钮标题字符串成功地转到 View2,该字符串也将分配给 View 2 按钮。 现在当用户从 View2 回到 View1 时, View1 按钮没有任何价值。如何将按钮值传递给 View1?

我尝试了委托方法..但没有成功:

已编辑

视图1

class PatientBreifInfoViewController: UIViewController, TasksViewDelegate {

    var passName: String!

    @IBOutlet weak var patientName: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        patientName.setTitle(passName, forState: .Normal)
    }

    func setName(name: String) {
        patientName.setTitle(name, forState: .Normal)
        print("View1")
        print(name)
    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

        if (segue.identifier == "toTasks") {
            let controller = segue.destinationViewController as! TasksViewController
            controller.delegate = self
            controller.passName = passName
        }
    }

}

视图2

protocol TasksViewDelegate: class {
    func setName(patientName: String)
}

class TasksViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    var passName : String!

    @IBOutlet weak var backButton: UIButton!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var patientName: UIButton!

    weak var delegate: TasksViewDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()

        patientName.setTitle(passName, forState: .Normal)
    }

    @IBAction func backButton(sender: AnyObject) {
        delegate!.setName(passName)
        self.navigationController?.popViewControllerAnimated(true)
    }

}

【问题讨论】:

  • 在您发布的代码中 passName 从未设置为仅声明。你有没有给它一个价值。当您在setName 中打印名称时,输出是什么?

标签: ios swift uiviewcontroller


【解决方案1】:

您的协议和委托应该可以正常工作。但是,您在 ViewController1 中实现 setName 并没有使用传递给它的 Name 参数:

func setName(Name: String) 
{

    passName = patientName

} 

应该改为:

func setName(Name: String) 
{

    patientName = Name

} 

您还应该遵循以小写名称开头的变量、参数和函数以及以大写名称开头的类型的快速命名约定。所以应该是setName(name: String) 而不是setName(Name: String),这也意味着在示例中将patientName = Name 更改为patientName = name

更新

因为当ViewController2 在屏幕上时,您的视图控制器将保留在内存中,所以viewDidLoad 在从ViewController2 转换到ViewController1 时不会再次被调用。相反,您可以直接在委托方法中设置按钮的标题。例如:

func setName(name: String)
{
    patientName.setTitle(name, forState: .Normal)
}

【讨论】:

  • "您应该将您的委托标记为弱以防止保留周期" ...这通常是正确的,但保留周期没有真正的风险,因为当您关闭 VC2 时,强引用周期已解决。但是 VC2 没有理由强烈引用其委托,因此您的 weak 观察仍然是谨慎的。但是你关于setName 方法的观点是正确的!
  • 谢谢@Rob。我想我反射性地将代表标记为weak,但是这些视图控制器之间没有父子关系,因此不存在保留周期的风险。我更新了我的答案。
  • @beyowulf:那是个愚蠢的错误……我的错!我确实进行了更改,并且根据 Rob 的建议,我的委托很弱,但 ViewController2 仍然没有将 Name 发送到 ViewController1。
  • @Spurti 您是否尝试过在ViewController1setName 实现中放置断点或打印某些内容,以查看它是否被调用以及传入的内容。
  • @beyowulf 在打印中显示正确的名称,但按钮标题仍为空。
【解决方案2】:

popViewController(animated:) 从导航堆栈中移除/弹出当前视图控制器。现在您可以使用导航堆栈的第一个视图控制器来访问其成员。 您可能不需要在这里使用委托

试试这个看看:

class TasksViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {



    @IBAction func backButton(sender: AnyObject) {
        self.navigationController?.popViewControllerAnimated(true)
        if let pbiViewController = self.navigationController?.viewControllers.first as? PatientBreifInfoViewController {
             pbiViewController.passName = passName
        }

    }

}


class PatientBreifInfoViewController: UIViewController {
    var passName: String?
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多