UIKit 中的 Segue 和委托
Segue and delegates in UIKit
我有 2 个控制器:MainVC 和 SideMenuVC。
我想使用 SideMenuVC 修改 MainVC,因此创建了 SideMenuVC 的委托(还有 Emdebed segue "name..." to "Side Menu View Controller" 在故事板上,因为 MainViewController 有子视图,其中包含 ContainerView - 这个容器是我们的 SideMenuVC。而这位代表按他应有的方式工作。
但是,由于应用程序中的逻辑,我还需要将数据从MAINVC发送到SIDEMENUVC.
所以我做了同样的事情 - 创建了第二个 VC 的另一个委托...但我发现,MainViewControllerDelegate 在 SideMenuViewController 中没有响应。而且我完全一无所知...
是的,我确实在两个 类 中实现了必要的协议!
下面两个VC的代码,附件中的故事板屏幕
MainViewController + MainViewControllerDelegate
protocol MainViewControllerDelegate{
func isImageLoaded(_ isLoaded:Bool)
}
class MainViewController: UIViewController {
/* ... */
var delegate: MainViewControllerDelegate?
var sideMenuViewController: SideMenuViewController?
private var isSideMenuPresented:Bool = false
private var isImageLoaded:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
self.isImageLoaded = false
self.setupUI()
self.delegate?.isImageLoaded(false)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "MainVC_SideMenuVC_Segue")
{
if let controller = segue.destination as? SideMenuViewController
{
self.sideMenuViewController = controller
self.sideMenuViewController?.delegate = self
}
}
}
/* ... */
//I'm using PHPicker, and when new image is selected, i want to send "true" via delegate
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true)
if let itemProvider = results.first?.itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self){
let previousImage = self.presentedImage.image
itemProvider.loadObject(ofClass: UIImage.self){ [weak self] image, error in
DispatchQueue.main.async {
guard let self = self, let image = image as? UIImage, self.presentedImage.image == previousImage else {
return
}
self.presentedImage.image = image
self.isImageLoaded = true;
self.delegate?.isImageLoaded(true)
}
}
}
}
SideMenuViewController + SideMenuViewControllerDelegate
protocol SideMenuViewControllerDelegate{
func hideSideMenu()
func performAction(_ type:OperationType)
}
class SideMenuViewController: UIViewController {
/*...*/
var delegate: SideMenuViewControllerDelegate?
var mainViewController: MainViewController?
private var menuData: [ExpandingCellModel] = []
private var isImageLoaded: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// self.mainViewController?.delegate = self
menuData = setupData()
setupUI()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let controller = segue.destination as? MainViewController {
controller.delegate = self
}
}
}
/* ... */
这是我认为正在发生的事情。
从 MainVC 到 SideMenuVC 有 发生 转场,但我认为 SideMenuVC 到 MainVC 之间没有转场 实际发生。
Happening 是关键字,因为从 MainVC 到 SideMenuVC 有一个 EmbedSegue,但是从 SideMenuVC 到 MainVC 的 segue 在哪里?你在情节提要中做了一些连接,但在我看来没有发生。
这就是为什么在 override func prepare
中按计划在 MainViewControllerDelegate
中调用并且委托正在设置但在 SideMenuViewController
中未设置的原因,因为 override func prepare
没有不会被调用,因为没有 segue 发生。
您可以做的是在 MainViewControllerDelegate
中设置 prepare
中的两个代表
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "MainVC_SideMenuVC_Segue")
{
if let sideMenuVC = segue.destination as? SideMenuViewController
{
sideMenuVC.delegate = self
// assign MainViewControllerDelegate here
self.delegate = sideMenuVC
}
}
}
现在检查数据是否也被发送回主视图控制器。
如果您的问题仍未解决,请查看并尝试this small example I set for you in github显示 mainVC 和 embeddedVC 之间传递的数据,它可能会给您一些提示。
您可以在此处查看此操作的结果:https://youtu.be/J7C7SEC04_E
我有 2 个控制器:MainVC 和 SideMenuVC。
我想使用 SideMenuVC 修改 MainVC,因此创建了 SideMenuVC 的委托(还有 Emdebed segue "name..." to "Side Menu View Controller" 在故事板上,因为 MainViewController 有子视图,其中包含 ContainerView - 这个容器是我们的 SideMenuVC。而这位代表按他应有的方式工作。
但是,由于应用程序中的逻辑,我还需要将数据从MAINVC发送到SIDEMENUVC.
所以我做了同样的事情 - 创建了第二个 VC 的另一个委托...但我发现,MainViewControllerDelegate 在 SideMenuViewController 中没有响应。而且我完全一无所知...
是的,我确实在两个 类 中实现了必要的协议!
下面两个VC的代码,附件中的故事板屏幕
MainViewController + MainViewControllerDelegate
protocol MainViewControllerDelegate{
func isImageLoaded(_ isLoaded:Bool)
}
class MainViewController: UIViewController {
/* ... */
var delegate: MainViewControllerDelegate?
var sideMenuViewController: SideMenuViewController?
private var isSideMenuPresented:Bool = false
private var isImageLoaded:Bool = false
override func viewDidLoad() {
super.viewDidLoad()
self.isImageLoaded = false
self.setupUI()
self.delegate?.isImageLoaded(false)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "MainVC_SideMenuVC_Segue")
{
if let controller = segue.destination as? SideMenuViewController
{
self.sideMenuViewController = controller
self.sideMenuViewController?.delegate = self
}
}
}
/* ... */
//I'm using PHPicker, and when new image is selected, i want to send "true" via delegate
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
dismiss(animated: true)
if let itemProvider = results.first?.itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self){
let previousImage = self.presentedImage.image
itemProvider.loadObject(ofClass: UIImage.self){ [weak self] image, error in
DispatchQueue.main.async {
guard let self = self, let image = image as? UIImage, self.presentedImage.image == previousImage else {
return
}
self.presentedImage.image = image
self.isImageLoaded = true;
self.delegate?.isImageLoaded(true)
}
}
}
}
SideMenuViewController + SideMenuViewControllerDelegate
protocol SideMenuViewControllerDelegate{
func hideSideMenu()
func performAction(_ type:OperationType)
}
class SideMenuViewController: UIViewController {
/*...*/
var delegate: SideMenuViewControllerDelegate?
var mainViewController: MainViewController?
private var menuData: [ExpandingCellModel] = []
private var isImageLoaded: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// self.mainViewController?.delegate = self
menuData = setupData()
setupUI()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let controller = segue.destination as? MainViewController {
controller.delegate = self
}
}
}
/* ...
这是我认为正在发生的事情。
从 MainVC 到 SideMenuVC 有 发生 转场,但我认为 SideMenuVC 到 MainVC 之间没有转场 实际发生。
Happening 是关键字,因为从 MainVC 到 SideMenuVC 有一个 EmbedSegue,但是从 SideMenuVC 到 MainVC 的 segue 在哪里?你在情节提要中做了一些连接,但在我看来没有发生。
这就是为什么在 override func prepare
中按计划在 MainViewControllerDelegate
中调用并且委托正在设置但在 SideMenuViewController
中未设置的原因,因为 override func prepare
没有不会被调用,因为没有 segue 发生。
您可以做的是在 MainViewControllerDelegate
prepare
中的两个代表
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "MainVC_SideMenuVC_Segue")
{
if let sideMenuVC = segue.destination as? SideMenuViewController
{
sideMenuVC.delegate = self
// assign MainViewControllerDelegate here
self.delegate = sideMenuVC
}
}
}
现在检查数据是否也被发送回主视图控制器。
如果您的问题仍未解决,请查看并尝试this small example I set for you in github显示 mainVC 和 embeddedVC 之间传递的数据,它可能会给您一些提示。
您可以在此处查看此操作的结果:https://youtu.be/J7C7SEC04_E