将另一个类的视图添加为 presentViewController 会导致 UIEvents 不起作用

Posted

技术标签:

【中文标题】将另一个类的视图添加为 presentViewController 会导致 UIEvents 不起作用【英文标题】:Adding view from another class as presentViewController causes UIEvents not working 【发布时间】:2017-07-04 02:52:04 【问题描述】:

我正在尝试使用有效的 UIElements 构建一个简单的库。我想做的是,从一个类实例创建 UIViewController 对象,并使用 presentViewController 方法将新的 ViewController 推送到当前 VC 堆栈上。

我可以看到 UIElements 已经成功添加到堆栈上,但是 GestureRecognizer 和 UIButton 的目标不起作用。当我检查 ViewDebug 时,这些设置是 <NSNull null>

这是我创建 UI 并将其放入当前视图堆栈的类方法。

-(void)displayAd

    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void)
        //Background Thread
        NSData * imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:fullpageCampaign.mainImage]];

        dispatch_async(dispatch_get_main_queue(), ^(void)
            //Run UI Updates
            fullPageView = [[UIViewController alloc] init];
            fullPageView.view.frame = CurrentVC.view.bounds;
            fullPageView.view.backgroundColor = [UIColor redColor];
            UIImageView *staticImageView = [[UIImageView alloc] init];
            staticImageView.frame = CurrentVC.view.frame;

            UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapDetected)];
            singleTap.numberOfTapsRequired = 1;
            [staticImageView addGestureRecognizer:singleTap];
            staticImageView.userInteractionEnabled = YES;
            [fullPageView.view addSubview:staticImageView];

            staticImageView.image = [UIImage imageWithData:imageData];
            [CurrentVC.view addSubview:fullPageView.view];
            //[fullPageView didMoveToParentViewController:self];
            [CurrentVC presentViewController:fullPageView animated:YES completion:^
                NSLog(@"Tagon Ads is about to showing.");
                UIButton *closeButton = [self createButtonWithAssetName:@"tagonAssets.bundle/close_button" TargetMethod:@"closeModal" andView:staticImageView];
                [staticImageView addSubview:closeButton];
                [CurrentVC.view bringSubviewToFront:closeButton];
            ];
        );
    );

CurrentVC 是我通过库的方法作为参数发送的当前 viewController,以便在其上添加新的 viewController 堆栈。

【问题讨论】:

查看***.com/questions/32964884/… 你确定这个链接和我的问题有关吗? 尝试设置 CurrentVC.view.clipsToBounds = YES;如果您的 ui 元素消失,则意味着您设置 CurrentVC.view.frame 不正确 我的 UIElements 并没有消失,它们只是不能像 GestureRecognizer、UIButton target 和 @selectors 等一样设置 Target 和 UIEvents。 请问,如果您已经将 fullPageView 的视图添加为子视图,为什么还要在 CurrentVC 上显示 fullPageView 【参考方案1】:

closeModal 操作在哪里?可能与您的currentVC 相同。如果是这样,您的closeButton 引用了currentVC,但您已经从那里转到fullPageView。所以,你的按钮失去了他的参考。

只需创建新控制器,在那里发送imageData,创建自定义初始化程序,在那里创建新的UIImageViewUIButton。这样,您的按钮将引用自己的根,您的问题应该得到解决。

【讨论】:

解决了我的问题,谢谢!从 xcode 创建一个新的视图控制器并在自定义类上分配它解决了固体:D【参考方案2】:

您的代码有几个问题,但首先,我会推荐一种不同的方法来完成您想要的。正如您在下面看到的,不推荐使用UIViewController 的实例。相反,请使用 storyboard 来设置您的视图控制器及其组件。您的代码会更小,您的设计将易于理解和更改。

You can read more about UIViewController here

您很少直接创建 UIViewController 类的实例。 相反,您创建 UIViewController 子类的实例并使用 这些对象提供特定的行为和视觉外观 你需要的。

这是另一个潜力。 fullpageCampaign.mainImage 是远程还是本地?如果位于远程,则应考虑改为NSURLSession

Read more about NSData:dataWithContentsOfURL here

不要使用这种同步方法来请求基于网络的 URL。为了 基于网络的URL,该方法可以阻塞当前线程数十 在慢速网络上的秒数,导致糟糕的用户体验,以及 在 ios 中,可能会导致您的应用被终止。

另一件小事是您将按钮添加到图像视图。虽然这没问题,并且当您允许用户对图像视图进行交互时可能会起作用,但更简洁的方法是创建一个 UIView 容器来保存图像视图和按钮。然后,该容器也可以是您将点击手势识别器附加到的视图。这样,图像视图可以保持为纯图像。

故事板方法

首先,创建一个UIIViewController 的子类。它应该看起来像这样:

FullPageViewController.h

#import <UIKit/UIKit.h>

@interface FullPageViewController : UIViewController

- (void)setImage:(UIImage *)adImage;

@end

FullPageViewController.m

#import "FullPageViewController.h"

@interface FullPageViewController ()

@property (weak, nonatomic) IBOutlet UIImageView *adImageView;

@end

@implementation FullPageViewController

- (void)setImage:(UIImage *)adImage 
    self.adImageView.image = adImage;


- (IBAction)tappedOnAd:(UIGestureRecognizer *)sender 
    if (sender.state == UIGestureRecognizerStateEnded) 
        // Do your ad thing here
    


- (IBAction)closeButtonPressed:(UIButton *)sender 
    [self dismissViewControllerAnimated:YES completion:nil];


@end

其次,创建一个故事板并将您的广告视图控制器添加到其中。然后将一个图像视图、一个按钮和一个点击手势识别器添加到您的视图控制器。点击手势识别器应该放在图像视图上以从那里捕获点击。您从 Object Library 中拉出所有这些对象。还记得为图像视图启用用户交互。在属性页面上有一个属性。

你现在应该有这样的东西:

注意右上角的类名,它应该是您刚刚创建的新视图控制器类的名称。还要注意从代码实例化视图控制器时需要的情节提要 ID adVC

下一步是连接对象。选择图像视图,然后从 Referencing Outlets 下的出口(圆环)拖动到位于视图控制器窗口顶部的视图控制器图标(带有正方形的黄色图标),然后选择 @ 987654337@。手势识别器应该已经连接,如果您在之前放置它时将其放在图像视图上。

接下来,连接关闭按钮的操作。从 Touch Up Inside 插座拖动到视图控制器图标(黄色),然后选择 closeButtonPressed: 方法。

接下来,将点击手势识别器连接到您的代码。从左侧列表中选择它,然后从 Sent Actions 拖动到视图控制器图标并选择 tappedOnAd:

最后,您展示广告的代码如下所示。此方法属于您的父视图控制器。

-(void)displayAd
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void)
        //Background Thread
        NSData * imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:fullpageCampaign.mainImage]];

        dispatch_async(dispatch_get_main_queue(), ^(void)
        //Run UI Updates
            UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"AdPage" bundle:nil];
            UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"adVC"];
            [vc setImage:[UIImage imageWithData:imageData]];
            [self presentViewController:vc animated:YES completion:^];
        );
    );

【讨论】:

您描述的方法是标准且有效的,但我在架构上的主要方法是创建库,它将是静态的,开发人员不会看到代码、手势和 UIView 元素。根据您的建议,该项目必须是公开的,并且需要使用情节提要实施一些步骤。

以上是关于将另一个类的视图添加为 presentViewController 会导致 UIEvents 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式将另一个视图控制器与按钮连接起来

将另一个网站添加为 serverMiddleware 的 Nuxt 模块

将另一个视图控制器推送到 UITabBarController 视图中

另一个集合视图中集合视图单元格的约束

将另一个视图附加到同一“文件所有者”

将另一个 UIViewController 的视图放在“主”UIViewController 中——委托方法