Web サービスからデータを受け取る UICollectionView があります。受け取ったデータに基づいて、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;
}
基本的に UIViewController である GridViewController があります。
@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 をボタンに接続しました。しかし、このボタンをクリックするたびに、GridIcon が ARC によって既に破棄されているため、nullpointer 例外が発生します。GridIcon をどこかに保持する必要がありますか? または、この (単純な?) 問題を克服するためのベスト プラクティスは何ですか?
私の GridIcon.m にあるメソッドは次のとおりです。
- (IBAction)cellClicked {
    NSLog(@"test");
}
そして、私の GridIcon.h ファイルには IBAction が記述されています:
@interface GridCell : UICollectionViewCell
- (IBAction)cellClicked;
@end
編集 :
ジャックスラッシュ、この本当に狂った構造に気づかせてくれたあなたの時間と努力に感謝します。このプロジェクトのセットアップ方法を説明しましょう。
AppDelegate.m で RootViewController として設定した MainViewController があります。次に、MainViewController で 2 つの UIVIewController を初期化します。それらの 1 つは、UICollectionView を設定する私の GridViewController です。
したがって、この 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] では、これらの UIViewcontrollers を初期化し、それらのビューをサブビューとして MainViewController に追加します。
これを達成するための最良の方法は何でしょうか?GridViewController とは別に UICollectionViewController を作成する必要がありますか? しかし、この UICollectionView は、画面のどの領域に描画するかをどのように認識しているのでしょうか?
GridCell 内の init メソッドでは、実際にこれを使用して GridCell の下に影を描画します。この init メソッドを使用せずにセルの下に描画するにはどうすればよいですか?
編集2: 上記の編集に加えて:
- 各 GridCell に UIImageView と UILabel があります。コードでそれらをどのようにターゲットにしますか?