【问题标题】:Protocols and Delegates not working with UICollectionReusableView协议和委托不适用于 UICollectionReusableView
【发布时间】:2015-11-20 12:20:20
【问题描述】:

我有一个启用了节页脚的UICollectionView。我创建了一个名为LeafletFooterViewUICollectionReusableView 的自定义子类,并声明了一些IBOutlets 和IBActions:

- (IBAction)dropboxButton:(id)sender;
- (IBAction)soundcloudButton:(id)sender;

在我的UICollectionViewClass 中,我有:

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *reusableview = nil;

    if (kind == UICollectionElementKindSectionFooter) {
        UICollectionReusableView *footerview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"FooterView" forIndexPath:indexPath];

        reusableview = footerview;
    }

    return reusableview;
}

LeafletFooterView 类的IBAction 中,我只是想呈现另一个viewController

- (IBAction)dropboxButton:(id)sender
{
    VideoWebViewController *video = [[VideoWebViewController alloc] init];
    UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:video];

    [self presentViewController:navigation animated:YES completion:nil];

    [video setSelectedVideo:@"https://www.dropbox.com/"];
}

错误是:

No visible @interface for 'LeafletFooterView' declares the selector 'presentViewController:animated:completion'. 

我已经在IBAction 方法中尝试了[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"www.dropbox.com"]];,虽然现在没有错误,但单击它不会打开带有网站的Safari。该方法肯定被调用; NSLogBreakpoint 证明了这一点。

更新

因此,在那之后不起作用,我尝试为此声明 Delegates 的过程,与这个问题的方式大致相同:Present view controller from NSObject subclass

这是我的LeafletFooterView

@class LeafletFooterView;
@protocol FooterViewDelegate <NSObject>
-(void)rowTapped;
@end
@interface LeafletFooterView : UICollectionReusableView
@property (weak, nonatomic) IBOutlet UILabel *label;
- (IBAction)dropboxButton:(id)sender;
@property(nonatomic,assign)id<FooterViewDelegate> delegate;

The LeafletFooterView.m is here: - (IBAction)dropboxButton:(id)sender
{
    NSLog(@"Dropbox");
    [self.delegate rowTapped];
}

现在在我的LeafletCollectionViewController,我有:

- (void)rowTapped
{
    NSLog(@"Is this getting called?");
    VideoWebViewController *video = [[VideoWebViewController alloc] init];
    UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:video];

    [self presentViewController:navigation animated:YES completion:nil];

    [video setSelectedVideo:@"https://www.dropbox.com/"];

}

当我运行这段代码时,这个方法实际上从未被调用过。 LeafletCollectionView 设置为使用FooterViewDelegate。在LeafletCollectionViewviewWillAppear 中,我尝试了以下操作:

LeafletFooterView *footer = [[LeafletFooterView alloc] init];
footer.delegate = self;

仍然没有真正调用rowTapped 方法。

用户应该能够单击LeafletFooterView 中的UIButton 并显示UIViewController。我该如何实现这一目标?任何指导将不胜感激。

【问题讨论】:

    标签: ios objective-c uiviewcontroller uicollectionview


    【解决方案1】:

    您需要在您的dataSource 所在的位置显示UINavigationController。因此,如果您尝试删除 IBAction 并以编程方式将方法添加到您的数据源要呈现 VideoWebViewController 的任何位置。

    然后在您的viewForSupplementaryElementOfKind 方法中,您将访问按钮并触发该方法。所以突然想起来了(有一段时间没用过objC了):

    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
    {
        UICollectionReusableView *reusableview = nil;
    
        if (kind == UICollectionElementKindSectionFooter) {
            LeafletFooterView *footerview = (LeafletFooterView *)[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"FooterView" forIndexPath:indexPath];
            [footerView.dropboxButton addTarget:self
                           action:@selector(dropboxTapped:)
                 forControlEvents:UIControlEventTouchUpInside];
    
            reusableview = footerview;
        }
    
        return reusableview;
    }
    
    -(void)dropboxTapped:(id)sender{
        // Present the controller here
    }
    

    我希望这会有所帮助:)

    编辑:更新您的问题后,我发现您选择了不同的路线。您只需要为 footerView 设置委托,如下所示:

    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
    {
        UICollectionReusableView *reusableview = nil;
    
        if (kind == UICollectionElementKindSectionFooter) {
            LeafletFooterView *footerview = (LeafletFooterView *)[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"FooterView" forIndexPath:indexPath];
            [footerView.dropboxButton addTarget:self
                                         action:@selector(dropboxTapped:)
                               forControlEvents:UIControlEventTouchUpInside];
            footerView.delegate = self
            reusableview = footerview;
        }
    
        return reusableview;
    }
    

    另外,不要忘记将视图投射到 LeafletFooterView,就像我在代码中使用 (LeafletFooterView *) 所做的那样,我希望它有效 :)

    【讨论】:

    • 谢谢伙计——这非常有帮助,而且说得通。我只是不太确定“因此,如果您尝试删除该 IBAction,而是以编程方式向您的数据源要呈现 VideoWebViewController 的任何人添加一个方法”.. 我不太确定该做什么
    • @amitsbajaj 当然,删除 IBAction(在界面生成器中,单击按钮,然后是插座,然后是操作的十字),然后尝试上面的代码
    • 嘿@daven - 抱歉 - 我认为代码有效,但我明确调用该方法进行测试,我忘记了取出该代码。此处的代码在您的回答中为我生成了一个错误,因为 footerView 没有对 .dropboxButton 等的引用。无论如何,我不得不在此处重新打开此案例。我已经使用代表更新了我的问题,以尝试使其正常工作。或者,如果您能够参考如何调用 dropboxButton 等来更新您的答案,那也可以。再次感谢!
    • 这就像一个魅力! footerView.delegate 是这里的关键,因为我将该委托设置在错误的位置并且带有断点,它只是一直显示该委托为零。这就像一个魅力,这真的很有帮助!谢谢男人 - 绝对接受和投票:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多