我有UICollectionView
使用- (void)scrollViewDidScroll:(UIScrollView *)scrollView
来确定用户何时滚动到底部。
我的UICollectionView
的所有者有一个方法可以向服务器发送命令并要求提供更多数据。
我想要做的是从我的UICollectionView
,特别是scrollViewDidScroll
内的所有者(我的viewcontroller)执行选择器。
我尝试使用以下代码执行此操作:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat offsetY = scrollView.contentOffset.y;
CGFloat contentHeight = scrollView.contentSize.height;
if (offsetY > contentHeight - scrollView.frame.size.height)
{
[[self superView] performSelector:@selector(onScrolledToBottom) withObject:nil];
}
}
注意:选择器onScrolledToBottom
是SEL
的{{1}}属性。
我得到的错误说:
UICollectionView
修改
我已经删除了我的代码以适应这个问题。
我在-[UIView onScrolledToBottom]: unrecognized selector sent to instance 0x7fc641e76e00
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView onScrolledToBottom]: unrecognized selector sent to instance 0x7fc641e76e00'
ViewController.m
对于我的....
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self initCollectionView];
}
....
- (void) getMoreInfo{
NSLog(@"Getting more info");
}
- (void) initCollectionView{
UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc]init];
flowLayout.itemSize = CGSizeMake(50.0, 60.0);
flowLayout.sectionInset = UIEdgeInsetsMake(20, 0, 20, 0);
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
flowLayout.headerReferenceSize = CGSizeMake(320.f, 30.f);
myCollectionView *mVC = [myCollectionView alloc] init: self.view: flowLayout: @selector(getMoreInfo)];
}
,myCollectionView
和.h
文件如下所示:
.m
和
#import <UIKit/UIKit.h>
@interface myCollectionView : UICollectionView<UIScrollViewDelegate, UICollectionViewDelegate, UICollectionViewDataSource>{
UIView *parentView;
SEL onScrolledToBottom;
}
@property UIView *parentView;
@property SEL onScrolledToBottom;
- (id)init: (UIView*) parent: (UICollectionViewLayout *)layout: (SEL)onScrolledToBottomSEL;
@end
答案 0 :(得分:2)
您正在获取超级视图而不是父级控制器,这是一个。其次,你不应该试着这样做。而是使用协议并将控制器作为委托传递给自定义集合视图。
@protocol MyCollectionViewScrollProtocol <NSObject>
- (void)scrolledToBottom;
@end
然后在ViewController中实现此协议并在CollectionView中
像这样创建一个弱属性委托:
@property(weak, nonatomic) id<MyCollectionViewScrollProtocol> delegate;
然后你就可以打电话了
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat offsetY = scrollView.contentOffset.y;
CGFloat contentHeight = scrollView.contentSize.height;
if (offsetY > contentHeight - scrollView.frame.size.height)
{
[self.delegate scrolledToBottom];
}
}
并且不要忘记从控制器设置委托属性。
按OP编辑:
控制器应在.h
文件中包含以下代码:
#import <UIKit/UIKit.h>
@protocol ViewControllerProtocol <NSObject>
- (void) Pong;
@end
@interface ViewController : UIViewController <ViewControllerProtocol>
@end
以及.m
文件中的以下代码:
#import "ViewController.h"
@import UIKit;
#import "myUnit.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
myUnit mU = [[myUnit alloc] init];
mU.linkToController = self;
[mU Ping];
}
......
- (void) Pong{
NSLog(@"Pong");
}
......
想要访问控制器的单元需要在.h
文件中包含以下代码:
#import <Foundation/Foundation.h>
#import "ViewController.h"
@interface myUnit : NSObject {
}
@property (weak, nonatomic) id <ViewControllerProtocol> linkToController;
- (void)Ping;
@end
想要访问控制器的单元需要在.m
文件中包含以下代码:
#import "myUnit.h"
#import "ViewController.h"
@implementation myUnit
- (void) Ping {
NSLog(@"Ping");
[self.linkToController Pong];
}
@end
答案 1 :(得分:1)
collectionView.parentView
将是ViewController.view
,完全是UIView
,没有名为onScrolledToBottom
的方法。
如果我对你想要的东西是正确的,这是一种方法,但是这真的是一种糟糕的方式来做这件事。
ViewController.m
中的
....
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self initCollectionView];
}
....
- (void) getMoreInfo{
NSLog(@"Getting more info");
}
- (void) initCollectionView{
UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc]init];
flowLayout.itemSize = CGSizeMake(50.0, 60.0);
flowLayout.sectionInset = UIEdgeInsetsMake(20, 0, 20, 0);
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
flowLayout.headerReferenceSize = CGSizeMake(320.f, 30.f);
myCollectionView *mVC = [myCollectionView alloc] initWithParentViewController:self layout:flowLayout selector:@selector(getMoreInfo)];
}
myCollectionView.h
中的
#import <UIKit/UIKit.h>
@interface myCollectionView : UICollectionView<UIScrollViewDelegate, UICollectionViewDelegate, UICollectionViewDataSource>{
UIViewController *_parentViewController;
SEL _onScrolledToBottom;
}
@property(weak) UIViewController *parentViewController;
@property SEL onScrolledToBottom;
- (id)initWithParentViewController:(UIView *)parentViewController layout:(UICollectionViewLayout *)layout selector:(SEL)onScrolledToBottomSEL;
@end
myCollectionView.m
中的
#import "myCollectionView.h"
@implementation myCollectionView
@synthesize parentViewController = _parentViewController;
@synthesize onScrolledToBottom = _onScrollToBotton;
- (id)initWithParentViewController:(UIView *)parentViewController layout:(UICollectionViewLayout *)layout selector:(SEL)onScrolledToBottomSEL{
self = [super initWithFrame: CGRectMake(0.0f, 0.0f, parent.frame.size.width, parent.frame.size.height) collectionViewLayout: layout];
if (self) {
_parentViewController = parentViewController;
self.delegate = self;
self.dataSource = self;
_onScrolledToBottom = onScrolledToBottomSEL;
}
return self;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat offsetY = scrollView.contentOffset.y;
CGFloat contentHeight = scrollView.contentSize.height;
if (offsetY > contentHeight - scrollView.frame.size.height)
{
[_parentViewController performSelector:@selector(onScrolledToBottom) withObject:nil];
}
}
警告:强>
MVC
中应该有Controller
来实施
协议,而不是视图。MyCollectionView
代替myCollectionView
作为班级名称。protocol-delegate
是最好的方式。答案 2 :(得分:1)
你的&#34; myCollectionView&#34;应该有一个委托(你将不得不为此创建一个协议),并采用一些方法:
- (void)myCollectionViewDidScrollToBottom:(myCollectionView *)collectionView
按照惯例,视图会将自身传递给此方法(就像任何tableView委托方法一样)。然后在initCollectionView
之后的myCollectionView *mVC = [myCollectionView alloc] init...
中,您必须将此委托设置为当前视图控制器并实现该方法。
mVC.delegate = self;
...
some other place in code
...
- (void)myCollectionViewDidScrollToBottom:(myCollectionView *)collectionView {
//do what's need to be done ;)
}
现在你的&#34; myCollectionView&#34;并不关心它在哪里,而是由#34;谁&#34;。任何想要使用它的人都可以使用任何自定义逻辑实现此方法并成为该视图的委托。这就是在这种方法中你可以调用任何必需的方法和任何其他东西。
这是如何运作的:
:)
答案 3 :(得分:0)
首先,我想对所有人说声谢谢。
我读完了你们写的所有内容,我受到启发。
特别是Stanislav Ageev的答案,他说
你得到的是superview而不是父控制器......
我试图将控制器本身作为UIViewController
而不是控制器的视图传递。
我还从@selector()
中移除了scrollViewDidScroll
并直接传递了选择器。
编辑我错过了zy.lius的回答。感谢他/她发布答案,这基本上解释了我在这里所做的事情,即使我自己想出来了。遗憾。
我的代码现在看起来像这样(.h / .m):
控制器
....
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self initCollectionView];
}
....
- (void) getMoreInfo{
NSLog(@"Getting more info");
}
- (void) initCollectionView{
UICollectionViewFlowLayout* flowLayout = [[UICollectionViewFlowLayout alloc]init];
flowLayout.itemSize = CGSizeMake(50.0, 60.0);
flowLayout.sectionInset = UIEdgeInsetsMake(20, 0, 20, 0);
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
flowLayout.headerReferenceSize = CGSizeMake(320.f, 30.f);
myCollectionView *mVC = [myCollectionView alloc] init: self: flowLayout: @selector(getMoreInfo)];
}
myCollectionView.h文件:
#import <UIKit/UIKit.h>
@interface myCollectionView : UICollectionView<UIScrollViewDelegate, UICollectionViewDelegate, UICollectionViewDataSource>{
UICollectionView *parentController;
SEL onScrolledToBottom;
}
@property UICollectionView *parentController;
@property SEL onScrolledToBottom;
- (id)init: (UICollectionView*) parent: (UICollectionViewLayout *)layout: (SEL)onScrolledToBottomSEL;
@end
和.m文件:
#import "myCollectionView.h"
@implementation myCollectionView
@synthesize parentController = parentController;
@synthesize onScrolledToBottom = onScrollToBotton;
- (id)init: (UIView*) parent: (UICollectionViewLayout *)layout: (SEL)onScrolledToBottomSEL{
self = [super initWithFrame: CGRectMake(0.0f, 0.0f, parent.view.frame.size.width, parent.view.frame.size.height) collectionViewLayout: layout];
if (self) {
parentController = parent;
self.delegate = self;
self.dataSource = self;
onScrolledToBottom = onScrolledToBottomSEL;
}
return self;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat offsetY = scrollView.contentOffset.y;
CGFloat contentHeight = scrollView.contentSize.height;
if (offsetY > contentHeight - scrollView.frame.size.height)
{
[parentController performSelector:@onScrolledToBottom withObject:nil];
}
}
这非常好用,可用于以各种方式与主控制器通信。
这很简单。
再次感谢鼓励我找到最有效的解决方案。