协议和委托不适用于 UICollectionReusableView
Posted
技术标签:
【中文标题】协议和委托不适用于 UICollectionReusableView【英文标题】:Protocols and Delegates not working with UICollectionReusableView 【发布时间】:2015-11-20 12:20:20 【问题描述】:我有一个启用了节页脚的UICollectionView
。我创建了一个名为LeafletFooterView
的UICollectionReusableView
的自定义子类,并声明了一些IBOutlet
s 和IBAction
s:
- (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。该方法肯定被调用; NSLog
和 Breakpoint
证明了这一点。
更新
因此,在那之后不起作用,我尝试为此声明 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
。在LeafletCollectionView
的viewWillAppear
中,我尝试了以下操作:
LeafletFooterView *footer = [[LeafletFooterView alloc] init];
footer.delegate = self;
仍然没有真正调用rowTapped
方法。
用户应该能够单击LeafletFooterView
中的UIButton
并显示UIViewController
。我该如何实现这一目标?任何指导将不胜感激。
【问题讨论】:
【参考方案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 是这里的关键,因为我将该委托设置在错误的位置并且带有断点,它只是一直显示该委托为零。这就像一个魅力,这真的很有帮助!谢谢男人 - 绝对接受和投票:)以上是关于协议和委托不适用于 UICollectionReusableView的主要内容,如果未能解决你的问题,请参考以下文章
如何在 UINavigationController 中使用协议和委托
AppDelegate 中的 UIActivityView 使用协议和委托