与后面的视图控制器交互

Posted

技术标签:

【中文标题】与后面的视图控制器交互【英文标题】:Interacting with the view controller behind 【发布时间】:2017-06-08 11:59:50 【问题描述】:

我知道 SE 上有几篇与此问题相关的帖子,但我无法绕过它们来找到适合我情况的解决方案。

我在视图控制器中有一个地图视图。我在地图视图 VC 的顶部呈现另一个视图控制器,其中 modalPresentationStyle 设置为 custom(容纳卡片视图):

对于这种情况,我想要的是地图视图在显示位置卡视图时仍然能够识别触摸,而位置卡仍然可以识别其内部的触摸。就像显示以下列表视图时 Apple 地图的功能一样。

我知道我无法通过视图控制器传递触摸,但我无法在两者之间做出决定:

将位置卡转储到我非常不喜欢的地图视图中, 通过addChildViewController展示位置卡,我不太清楚如何实现以达到我想要的效果。

This SE question 给出了一个详细的答案和一个关于模仿 Apple Maps 界面的小示例项目,尽管我仍然不知道如何解决我的问题。

【问题讨论】:

您希望您呈现的视图(卡片视图)检测触摸吗? @AravindAR 是的,那也是。更新问题... 为什么不直接使用自定义视图并将其添加为子视图而不是全新的视图控制器? @CoderFrom94 能否请您多指教一下,可以提供一个示例... @CanSürmeli,几周前我在做一个类似的项目,我需要一个类似于你在地图上的界面。我使用了一个自定义视图,其中包含一个表格视图和一些自定义单元格。我会在不需要时隐藏视图,并在需要时在视图中设置表格视图的数据源。它实现了您在此问题中解释的功能。我将在深夜(IST)输入一个示例代码,因为我现在正处于发布的中间。 :) 【参考方案1】:

我选择将位置卡视图转储到地图视图中。 但是我不喜欢它。

问题是我不希望地图视图中的任何位置卡逻辑。但与此同时,ios 没有提供基础架构,视图控制器之间的触摸传输基本上是不可能的,建议的解决方法似乎很难实现。

首先,我将位置卡视图从视图控制器迁移到结构。

然后,我定义了一个名为LocationCardPresentable 的协议,当扩展它时,要求Self 的类型为MapVC。因此,在协议扩展中,我可以像在 MapVC 中一样工作,但实际上不是。协议扩展有多种方法来显示和关闭我可以从MapVC 内部调用的位置卡。

【讨论】:

【参考方案2】:

所以我现在设法通过使用 loadView()point(inside) 的组合来替换呈现的 ViewController 中的 rootView 来解决这个问题。

首先,创建一个 UIView 的子类,您将在任何您希望在下面的 ViewControllers 上传递触摸的 ViewControllers 中将其用作您的 rootView:

IgnoreTouchesView

import UIKit

类 IgnoreTouchesView: UIView

override init(frame: CGRect) 
    super.init(frame: frame)



required init?(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")


override func point(inside point: CGPoint, with event: UIEvent?) -> Bool 
    for view in self.subviews 
        if view.isKind(of: UIButton) 
            let foundButtonView = view

            if foundButtonView.isUserInteractionEnabled && !foundButtonView.isHidden && foundButtonView.point(inside: self.convert(point, to: foundButtonView), with: event) 
                return true
            
        
    

    return false

point(inside) 函数检查用户是否点击了 OverlayVC 中的任何 UIButton,在这种情况下仍应处理触摸。任何其他接触都会传递给下面的 VC。这可以通过只忽略 rootView 来完成,但我还没有想出如何安静地做到这一点。

然后,在您要呈现的 VC 中,添加以下内容:

let ignoreView: IgnoreTouchesView = 
    let view = IgnoreTouchesView(frame: .zero)
    view.translatesAutoresizingMaskIntoConstraints = false
    return view
()

override func loadView() 
    view = ignoreView

现在将 ViewControllers 添加到您原来的 ViewController 中:

lazy var overlayVC : OverlayVC = 
    let vc = SongOverlayVC()
    vc.view.translatesAutoresizingMaskIntoConstraints = false
    vc.delegate = self
    return vc
()

viewDidLoad()
    view.addSubview(songOverlayVC.view)

就是这样:)

如果您遇到任何问题,请告诉我。

【讨论】:

以上是关于与后面的视图控制器交互的主要内容,如果未能解决你的问题,请参考以下文章

将导航控制器栏按钮与嵌入容器视图交互

管理容器视图控制器内同级视图控制器之间的交互

新的视图控制器出现然后消失在 CCScene 后面

Cocoa Touch 中的 MVC:视图和模型如何交互?

iOS_book 02 - 基本交互(约束视图控制器基本控件:按钮文本框分段控件开关标签图像控件)

iOS UISearchController Class Reference