您将如何从子视图中呈现ViewController?

Posted

技术标签:

【中文标题】您将如何从子视图中呈现ViewController?【英文标题】:How would you presentViewController from subview? 【发布时间】:2016-04-21 08:02:20 【问题描述】:

假设我们有一个自定义控件,在某些状态下应该弹出选项列表供用户选择(UIAlertController)。通常,当我们在视图控制器中时,我们使用 presentViewController 方法,但在这种情况下,我们无法访问拥有该方法的父 UIViewController。尽管似乎有某种方法可以从子视图中访问 UIViewController,但它被认为是违反 MVC 设计模式的。那你会怎么做呢? 我想保持视图控制器尽可能精简和自定义视图(uicontrol)自给自足,所以我不想将此逻辑移动到视图控制器。 尽管您的所有意见和建议都受到欢迎和赞赏。

【问题讨论】:

How to present UIAlertController when not in a view controller?的可能重复 一个选项是委托,您可以从自定义视图调用委托方法到view controller 以呈现视图控制器 【参考方案1】:

您始终可以使用应用程序 rootviewController 来显示警报视图控制器 :) 您不必总是选择视图控制器的视图 :) 无论您的控件在哪里,都可以访问 rootview 控制器 :)

这是你可以做的:)

目标 C

 AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[delegate.window.rootViewController presentViewController:your_alert_view_controller animated:YES completion:nil];

斯威夫特

let appDelegate : AppDelegate? = UIApplication.sharedApplication().delegate as? AppDelegate
if let unwrappedAppdelegate = appDelegate 
     unwrappedAppdelegate.window!.rootViewController! .presentViewController(alert, animated: true, completion: nil)

希望我的回答对你有帮助:)

【讨论】:

你有 .绑定到:) ? @james : 对不起,伙计,我知道你 :|我是不是写错了什么?? @Sandeep 工作。像这样称呼它 - UIApplication.sharedApplication().keyWindow?.rootViewController?.presentViewController(optionMenu, animated: true, completion: nil)【参考方案2】:

我更喜欢委托或目标操作。这是更清洁的方式,因为在这种情况下您不使用AppDelegate。此外,显示某些内容不是子视图的责任。委托示例:

protocol MyViewDelegate: class 
    func somethingHappenedToMyView(view: MyView)


class MyView: UIView 
    weak var delegate: MyViewDelegate?

    func somethingHappened() 
        delegate?.somethingHappenedToMyView(self)
    


class ViewController: UIViewController, MyViewDelegate 
    override func viewDidLoad() 
        super.viewDidLoad()
        myView.delegate = self
    

    func somethingHappenedToMyView(view: MyView) 
        presentViewController(someViewController, animated: true, completion: nil)
    

目标动作示例:

class MyView: UIControl 
    func somethingHappened() 
        sendActionsForControlEvents(.ValueChanged) // .ValueChanged is an example. Maybe other events will be more meaningful for your situation
    


class ViewController: UIViewController, MyViewDelegate 
    override func viewDidLoad() 
        super.viewDidLoad()
        myView.addTarget(self, action: #selector(self.somethingHappenedToMyView(_:)), forControlEvents: .ValueChanged)
    

    func somethingHappenedToMyView(view: MyView) 
        presentViewController(someViewController, animated: true, completion: nil)
    

【讨论】:

是的,我认为使用委托确实应该是更好的方法。但是这种方式 MyCustomControl 不再是独立的解决方案,我需要向视图控制器提供数据以某种方式呈现它。然后在用户选择一些值后,我需要将其返回给 ui 控件并决定下一步做什么。【参考方案3】:

从委托根视图控制器呈现在许多情况下(嵌套呈现、选项卡的更多控制器等)将不起作用。

通过遍历视图的响应者链更好地找到父 UIViewController 响应者。使用这个宏:

#define UIViewParentController(__view) ( \
UIResponder *__responder = __view; \
while ([__responder isKindOfClass:[UIView class]]) \
__responder = [__responder nextResponder]; \
(UIViewController *)__responder; \
)

在视图中:

UIViewController *parentViewController = UIViewParentController(self);

相关问题:one、two。

【讨论】:

以上是关于您将如何从子视图中呈现ViewController?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 UIViewController 呈现为部分视图?

如何从 viewController 的视图中呈现 UIViewController

从子视图中访问 UIViewController 方法

从子视图中引用包含 UIView?

从子视图控制器呈现主视图控制器

iPhone,iOS 8:如何呈现比原始视图控制器更小的 ViewController?