【问题标题】:UIButton Class to dismiss view controllerUIButton 类关闭视图控制器
【发布时间】:2014-05-07 09:50:40
【问题描述】:

我是 ObjectiveC 的新手(+/- 两周),所以我很难实现在其他语言中很容易实现的东西,我希望有人能提供帮助(如果可能的话):

背景: 我有一个在相当复杂的体系结构中包含许多窗口的界面,每个窗口都可以调用其他窗口(ViewControllers、TableViewControllers、Tab/Nav VC 等)。 我现在正在使用“模态”,因为我不知道如何在没有错误的情况下使用 Push。 每个窗口都有一个调用dismissViewController的按钮,这个按钮在任何地方都是相同的(相同的图形、位置等)。

我认为为它们中的每一个创建一个 IBAction 并给出完全相同的名称和相同的功能很麻烦,所以我决定创建一个 UIButton 类别的“自定义类”,将所有参数放在那里,然后给出故事板中的按钮是一个类,因此可以轻松配置它们。

问题: 虽然这对于某些具有复杂功能的按钮非常有效,但它不适用于dismissViewController ...我想这是因为我使用的是“self”,这在这里是错误的,但我不知道如何使用“parent” ? 这是代码

#import "returnToMainMenuButton.h"

@implementation returnToMainMenuButton

-(IBAction)returnToMainMenu:(id)sender
{
    [self dismissViewControllerAnimated:YES completion:nil];

}
@end

问题: 1)有可能做到这一点吗?因为我真的不喜欢在我的代码中重复完全相同的步骤 10 次,所以我宁愿调用一次操作而不是声明它并启动它。 (我想有可能,因为我们可以选择预定义的类型,如“添加”、“保存”等)

2) 如果是,您能否告诉我如何做到这一点?

3) 如果没有,还有其他方法可以做这样的事情吗?

非常感谢。 干杯

【问题讨论】:

  • 您是否在您正在开发的应用程序的任何地方使用了导航控制器?
  • @Ashutosh 是的,我在某些视图中使用它,但不在主屏幕上。主屏幕是简单的 VC,我在表格之前有一些 NC(以允许正常添加/编辑)。
  • 好的,所以如果您将 UINavigationController 作为您当前所在的 viewController 的根,那么您将不得不从中弹出而不是关闭它。如果我是对的,请告诉我,以便我给你一个简短的答案。
  • @Ashutosh 谢谢你的回答。可悲的是,我并不总是将 NC 作为我观点的根源。例如,我有一个带有垂直选择的屏幕(如游戏选择屏幕),一些按钮调用单个视图(VC),必须将其关闭(返回按钮或取消自定义按钮)...
  • Objective-C 类名应该大写。

标签: ios objective-c uibutton


【解决方案1】:

这里的主要问题是UIButton 不知道名为dismissViewControllerAnimated:completion: 的方法,这是UIViewController 方法。

此外,没有办法从UIView(或子类,您的类是子类的子类)开始并到达其视图控制器。 UIViewController 可以访问它的所有视图和子视图。但是无法保证您的 UIButton 在视图层次结构中的嵌套深度,我们必须遍历每个视图并找到与您的按钮类匹配的视图。

我能想到的唯一真正的选择是创建一个UIViewController 子类,其方法如下所示:

- (IBAction)exit:(id)sender {
    if (self.navigationController) {
        [self.navigationController popViewControllerAnimated:YES];
    } else {
        [self dismissViewControllerAnimated:YES completion:nil];
    }
}

所以现在这段代码将摆脱视图控制器,无论它是否在导航控制器中(注意,if 检查可能不够好——可能需要更多条件)。

现在,让所有的视图控制器成为这个视图控制器的子类。并将您的常规、非子类化 UIButtons 与如下所示的方法挂钩:

- (IBAction)exit:(id)sender {
    [super exit:sender];
}

如果您在按下按钮时需要执行任何其他代码,可以将其放在对super 的调用周围。您仍然必须将按钮连接到每个视图控制器......除非您想为每个按钮提供对它需要关闭的视图控制器的引用。但这种方式不那么混乱,更容易维护。视图控制器需要负责何时被解雇或即将呈现新的视图控制器。更改视图控制器的逻辑不应该在视图控制器类之外。

【讨论】:

    【解决方案2】:

    对于这个东西,在按钮的动作上你可以获得当前视图控制器的父视图控制器,现在如果它是 UINavigationViewController 那么你可以弹出视图,否则你可以关闭它。

    【讨论】:

    • 谢谢解答,不知如何获取父视图?我见过一些方法,例如“currentModalViewController”,但它们似乎已被弃用。我会用“currentViewController”试试运气,但不确定它是否有效。
    • 感谢您的评论。可悲的是,我缺少“yourView”,因为我只有一个 UIButton 类中的按钮。但是,我可以这样做: self(the button).window.rootViewController dismiss... 但这会将我带到根目录,而将 parentViewController 添加到该语句是不一致的,并且会带回一些视图。
    • UIButton 通常没有只为它们自己提供的视图控制器。它们是 UIView 子类,而不是 UIViewController。您可以跟随按钮的superview 一直到主窗口,但无法从视图到达其视图控制器——只有相反的情况。
    • 我会记住这一点,谢谢(我正处于学习 iOS 开发的早期阶段,因此不确定坏/好的做法)。我通过添加委托解决了获取其实际父视图的问题,如下所示: 在按钮中:@property(nonatomic, strong) UIViewController *delegate; [self.delegate dismissViewControllerAnimated:YES completion:NO]; 在视图控制器中:ButtonClass *button = [[ButtonClass alloc] init]; button.delegate = self;
    【解决方案3】:

    所以,我实际上解决了一半以上的问题,虽然我仍然找不到确切的父视图(或当前视图),但我可以快速进行设置,这为我节省了大量时间。

    基本上,在 UIButton 类 (ButtonClass.m) 中,我在“initWithFrame”中启动按钮,如下所示:

    - (id)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self)
        {
            // Styling goes here, such as title, image, and position/alignment
            // Adding an IB Action as follow:
            [self addTarget:self action:@selector(theAction:) forControlEvents:UIControlEventTouchUpInside];
            [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil];    
        }
        return self;
    }
    

    动作,在同一个文件上:

    -(IBAction)theAction:(id)sender
    {
        //This works, but returns me to the root view
        [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
        //This works really weirdly and is inconsistent [self.window.rootViewController.parentViewController dismissViewControllerAnimated:YES completion:nil];
    }
    

    从这里开始,不需要在任何地方使用 Storyboard,在任何视图中我都需要按钮,这样做就足够了:

    #import "ButtonClass.h"
    

    然后

    UIButton *button = [[ButtonClass alloc] init];
    [self.view addSubview:button];
    

    我希望这可以帮助任何试图通过将操作/样式绑定到按钮来减少工作的人(与当前视图无关的任何操作都可以工作,例如访问核心数据或多点连接等)。

    如果有办法在创建时将当前视图的self 传递 到按钮,我很高兴知道。我知道这应该是可能的,但不知道如何在 Objective-C 中做到这一点。 谢谢

    【讨论】:

    • 您可以编写一个自定义的初始化方法,将 self 作为参数。但你不应该。同样,正如我在回答中所说,视图 CONTROLLER 应该控制自己并确定它何时关闭、呈现新视图等。虽然子类化 UIButton 是每次获得相同外观按钮的好方法,如果你想要那个每次触摸按钮都会触发相同的方法,您的解决方案是将UIViewController 子类化并提供默认触发方法。现在你为你的所有视图控制器子类化这个控制器,如果你愿意,可以重写那个方法来添加它。
    猜你喜欢
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    • 2018-11-27
    • 2013-01-01
    • 2014-08-27
    • 2012-01-28
    相关资源
    最近更新 更多