我有一个UICollectionView,它从Web服务接收数据。根据它收到的数据,它在我的UICollectionView上绘制单元格。每个单元格都是一个自定义类,它扩展了UICollectionViewCell。每个UICollectionViewCell都通过.nib加载。我的init方法如下所示:
@implementation GridCell
- (id)initWithFrame:(CGRect)frame
{
if (self)
{
// Initialization code
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:@"GridCell" owner:self options:nil];
if ([arrayOfViews count] < 1) {
return nil;
}
if (![[arrayOfViews objectAtIndex:0] isKindOfClass:[UICollectionViewCell class]]) {
return nil;
}
self = [arrayOfViews objectAtIndex:0];
// It is important that you set the properties of the view after the above assignment
// because self is assigned to the nib after that call.
self.layer.masksToBounds = NO;
self.layer.shadowColor = [[UIColor blackColor] CGColor];
self.layer.shadowOffset = CGSizeMake(0.0, 1.0);
self.layer.shadowOpacity = 0.17;
self.layer.shadowRadius = 0.35f;
self.layer.shouldRasterize = YES;
}
return self;
}
我有一个GridViewController,它基本上是一个UIViewController:
@implementation GridViewController
- (id)initWithSize:(CGFloat)frameWidth :(CGFloat)frameHeight {
self = [super init];
if(self) {
// Have the getGridView returning the initialized view
// then assign it to the GridViewControllers view property
self.view = [self getGridView:frameWidth:frameHeight];
}
return self;
}
-(UIView *)getGridView:(CGFloat)width :(CGFloat)height {
UIView *gridHolder = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc]init];
[flow setScrollDirection:UICollectionViewScrollDirectionHorizontal];
CGRect screen = [[UIScreen mainScreen] bounds];
CGFloat screenheight = screen.size.height;
// It is an iphone 5, setup the cellsize and the spacing between cells.
if(screenheight > 480) {
[flow setItemSize:CGSizeMake( (gridHolder.frame.size.width / 1.85) , (gridHolder.frame.size.height / 3.25) )];
[flow setSectionInset:UIEdgeInsetsMake(0, 0, 0, 0)];
[flow setMinimumInteritemSpacing:0];
[flow setMinimumLineSpacing:10];
// It is an iphone 4, setup the cellsize and the spacing between cells.
} else {
[flow setItemSize:CGSizeMake( (gridHolder.frame.size.width / 2.5) , (gridHolder.frame.size.height / 3.1) - 10)];
[flow setSectionInset:UIEdgeInsetsMake(0, 0, 0, 0)];
[flow setMinimumInteritemSpacing:0];
[flow setMinimumLineSpacing:10];
}
self.grid = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, gridHolder.frame.size.width, gridHolder.frame.size.height) collectionViewLayout:flow];
[_grid setBackgroundColor:[UIColor colorWithRed:0.961 green:0.961 blue:0.961 alpha:1]];
[_grid setDataSource:self];
[_grid setDelegate:self];
[_grid setBounces:NO];
[_grid registerClass:[GridCell class] forCellWithReuseIdentifier:Cell];
[gridHolder addSubview:self.grid];
return gridHolder;
}
这个UIViewController也是我的UICollectionViewDataSource。所以我有以下方法:
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [releases count];
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(10, 10, 10, 10);
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
GridCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:Cell forIndexPath:indexPath];
return cell; // <-- finally return the cell
}
我在细胞上添加了一个UIButton。我将IBAction连接到按钮。但每次我点击这个按钮,我都会得到一个nullpointer异常,因为ARC已经抛弃了GridIcon。我必须在某个地方保留GridIcon吗?或者,克服这个(简单?)问题的最佳做法是什么?
驻留在我的GridIcon.m中的方法是:
- (IBAction)cellClicked {
NSLog(@"test");
}
我的GridIcon.h文件中描述了一个IBAction:
@interface GridCell : UICollectionViewCell
- (IBAction)cellClicked;
@end
修改:
jackslash,谢谢你花时间和精力让我意识到这个疯狂的结构。让我解释一下我是如何设置这个项目的。
我有一个MainViewController,我在AppDelegate.m中设置为RootViewController。然后在我的MainViewController中使用init 2 UIVIewController。其中一个是我的GridViewController,它设置了UICollectionView。
因此,这个UICollectionView的数据源是我初始化的UIViewController。我需要为这个UIViewController绘制一个屏幕区域,所以我将另一个UIViewController的高度赋予GridViewController。并且getGridView方法获取屏幕的高度减去另一个UIViewConroller视图的视图高度。
结构是这样的:
@interface MainViewController: UIViewController
// These next two classes both extend UIViewController
@property(nonatomic, strong) GridViewController *gridViewcontroller;
@property(nonatomic, strong) BottomBarController *bottomBarcontroller;
@end
在我的MainViewController.m [viewDidLoad]中,我都启动了那些UIView控制器,并将它们的视图作为子视图添加到MainViewController。
那么实现这一目标的最佳方法是什么?我应该将UICollectionViewController与我的GridViewController分开吗?但是,这个UICollectionView如何知道要在哪个屏幕区域上绘制?
对于我的GridCell中的init方法,我实际上使用它在我的GridCell下面绘制一个阴影。如果没有这个init方法,我如何在我的单元格下面绘制图形?
编辑2: 除了上面的编辑:
答案 0 :(得分:5)
所以这里发生的事情在很多方面搞砸了。
- (id)initWithSize:(CGFloat)frameWidth :(CGFloat)frameHeight
,人们希望从名称中取CGSize
但它需要两个花车-(id)initWithSize::
方法初始化视图控制器GridCell
类文件与其包含的类名称不同(错误格式)你似乎从根本上误解了这一切是如何起作用的。我会在这里帮助你,但请记住,你应该花时间去理解这里的一切,并且还要去阅读更多关于iOS的内容。也许看一下iTunes U(CS193p)上的iOS课程,它是免费的,可以帮助你编写更好的代码。
这很疯狂。如果你想从xib加载你的UICollectionViewCell
子类,你不要这样做,你可以在UICollectionViewController
子类中注册带有集合视图的nib,如下所示:
UINib * cellNib = [UINib nibWithNibName:@"GridCell" bundle:[NSBundle mainBundle]];
[self.collectionView registerNib:cellNib forCellWithReuseIdentifier:cellReuseIdentifier];
然后在
中获取单元格时,将从xib文件中加载单元格- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
确保将GridCell.xib
文件中的单元格类设置为GridCell
子类。永远不要再写这样的init方法了。
-(UIView *)getGridView:(CGFloat)width :(CGFloat)height
始终在Objective-c方法签名中命名所有参数。
-(UIView *)getGridViewWithWidth:(CGFloat)width andHeight:(CGFloat)height
英里和英里更好。但你最好使用CGSize
...
- (id)initWithSize:(CGFloat)frameWidth :(CGFloat)frameHeight
在Objective-c中,我们希望这会采用CGSize参数,因为您的方法名为“initWithSize”。 CGSize
是一个带有width
和height
的C结构。您可以使用CGSizeMake(<width>,<height>)
创建一个。你可以让你的init方法看起来像这样:
- (id)initWithSize:(CGSize)size
但你真的不想用UIViewController
来发起CGSize
...
有一个原因UIViewController
没有任何类型的init方法可以采用任何类型的大小或维度。视图控制器的想法是它的视图大小由其父(或窗口)设置,然后负责在其视图中绘制其内容,无论大小如何。作为UIViewController
子类在UIKit
中,可以加载其他视图和视图控制器,以显示您应该显示的内容。查看方法-(void)viewDidLoad
并覆盖它。但即便如此,如果您只是将UICollectionViewController
子类化,因为您不需要任何类型的容器,而您的视图控制器的视图属性已经是一个collectionView以及许多其他好处。
将您的GridIcon.h
和GridIcon.m
文件重命名为其包含的类的名称。如果不是其他所有参与您项目工作的人,请始终遵循此规则,以确保您未来的理智。
最后,它崩溃的原因不是因为ARC或其他技术失败,因为这里的实施存在真正的基本问题。