使用委托传递数据

时间:2019-01-13 04:34:30

标签: swift

我正在尝试在A和C之间传递数据,其中A是第一个控制器,C是第三个控制器。现在,我知道如何将数据从A传递到B,再将B传递给A,然后在B中创建协议,并在视图控制器内部创建委托。看起来像这样。

控制器

class AController: UIViewController, BControllerDelegate {
  func bControllerButtonPress() {
    view.backgroundColor = .red
  }

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

  @IBAction func showBController() {
    performSegue(withIdentifier: "ShowBController", sender: nil)
  }
}

B控制器

protocol BControllerDelegate {
  func bControllerButtonPress()
}

class BController: UIViewController {
  var delegate: BControllerDelegate?

  @IBAction func buttonPress() {
    delegate?.bControllerButtonPress()
    self.dismiss(animated: true, completion: nil)
  }
} 

现在我将如何使用C控制器甚至D控制器来执行此操作。原因我有一个导航控制器,在控制器C中我创建一个新Item并弹出到根视图控制器。然后,我想更改UI,但似乎无法弄清楚。非常感谢您的帮助。

更多详细信息说明

控制器A,具有一个登录按钮的登录控制器,可将我带到控制器B。控制器B,电子邮件控制器。控制器C,用户名/名称控制器。控制器D,密码控制器。因此,从控制器B,我将电子邮件传递到控制器C,依此类推,直到控制器D。这是我创建新用户的地方。在Controller D中创建新用户时,我弹出到根视图控制器。然后,这是我想在控制器D中创建新用户之后,从控制器A对控制器E进行隔离的过程。控制器A,B,C,D都位于一个导航控制器中。

那么看着@bsod和@Caleb的答案似乎是我在A-B-C-D控制器之间传递了委托还是数据模型?

3 个答案:

答案 0 :(得分:0)

  

现在我将如何使用C控制器甚至是D控制器来完成此操作。

这是围绕data model组织应用程序的很好理由。应用程序委托或第一视图控制器可以创建模型,该模型应包含应用程序的数据和业务逻辑。每个视图控制器都将对模型的引用传递给它创建的任何其他视图控制器,因此您不必担心在视图控制器之间传递数据。如果您的视图控制器C或D对模型进行了某些更改,则无需将它们明确地移交给A ... A只是通过与C或D使用的相同数据模型进行对话来自动获取更新的数据。

这是一个具体的例子。假设您要为销售人员建立组织者。因此,您的数据模型可能称为OrganizerModel,并且其中包含customers的列表。您可以点击按钮以查看地图上的所有客户位置,然后可以点击地图上的特定位置以查看和编辑客户数据。那么,这些更改应如何传达回应用程序的其余部分?假设有一个MainViewController,它显示了应用程序的主视图,并允许您访问客户列表,供应商列表,产品目录,日历等。当您点击按钮查看客户列表时,{{1} }选择MainViewController,并在CustomerListViewController中执行以下操作:

prepare(for:sender:)

因此,现在客户列表控制器可以访问客户列表,这就是它要做的全部工作。从那里,用户可以点击一个按钮以查看地图上的所有客户,然后guard let customerListController = segue.destinationController as CustomerListViewController else { //... } customerListController.customerList = self.organizerModel.customerList 会选择CustomerListViewController,再次执行以下操作:

CustomerMapViewController

因此,CustomerMapViewController会显示一个地图,其中包括每个客户的小图标,并且当用户点击其中一个图标时,它会选择到CustomerViewController,后者只需一个客户的记录即可完成其所做的所有工作:

guard let customerMapController = segue.destinationController as CustomerMapViewController else {
   //...
}
customerMapController.customerList = self.customerList

现在,我们遇到了类似guard let customerController = segue.destinationController as CustomerProfileViewController else { //... } customerController.customer = self.customerList[selectedCustomer] 的情况,其中视图控制器与第一个控制器相距几处跳动,正在更改某些数据。但是,当A->B->C->D对其CustomerProfileViewController进行一些更改时,由于customerMainViewController都已经被传送到MainViewController了,因此无需将信息一直发送回CustomerProfileViewController。使用相同的数据; customerMainViewController使用的整体模型的一部分。

答案 1 :(得分:0)

严格回答您的问题,代表可以链接有或没有协议。使用协议:

protocol DoSomething: AnyObject {
    func doSomething()
}
class VCA: UIViewController, DoSomething {
    func doSomething() {
        print("do something")
    }
    func push() {
        let b = VCB()
        b.delegate = self
    }
}
class VCB: UIViewController, DoSomething {
    weak var delegate: DoSomething?
    func doSomething() {
        delegate?.doSomething()
    }
    func push() {
        let c = VCC()
        c.delegate = delegate // instead of declaring self as the delegate
                              // you can declare the delegate (which is VCA)
    }
}
class VCC: UIViewController {
    weak var delegate: DoSomething?
    func doSomething() {
        delegate?.doSomething()
    }
}

您还可以放弃协议,只需将委托键入第一个视图控制器即可:

class VCA: UIViewController {
    func doSomething() {
        print("do something")
    }
    func push() {
        let b = VCB()
        b.delegate = self
    }
}
class VCB: UIViewController {
    weak var delegate: VCA?
    func push() {
        let c = VCC()
        c.delegate = delegate
    }
}
class VCC: UIViewController {
    weak var delegate: VCA?
    func doSomething() {
        delegate?.doSomething()
    }
}

仔细考虑如何构造视图控制器并作为委托模式传递数据不是唯一的选择-但是,这是基石。

答案 2 :(得分:-1)

您可能还有其他选择, 第一个:您必须创建从A到B的代表,然后再创建B到C的代表。(如果您不希望视图控制器B出现,而不是动画false建议)

或者您可以选择在ciew控制器之间创建通知总线 您可以对其使用“ NotificationCenter”方法。在其中定义相同的观察者和接收者的地方,您将获得定义该通知的接收者的类的控件。

在按下新的视图控制器时,请删除所有通知观察器。