web-dev-qa-db-ja.com

UICollectionViewCellレジスタクラスは失敗しますが、レジスタペン先は機能します

私のUICollectionViewCell用にカスタムUICollectionViewControllerを作成すると、ペン先を登録することで機能します。ただし、クラスごとの登録に失敗します。

registerClass()の使用-失敗

クラスによる登録は正しいようです-ビルドしますが、実行時に例外をスローして、UIViewからオプションの要素をアンラップします。アウトレットを参照せずに実行されます。ただし、コレクションビュー内にセルは表示されません。

collectionView?.registerClass(MyCollectionViewCell.self, 
                              forCellWithReuseIdentifier: "myCell")

明らかに、ビューはロードされていません。ただし、セルのカスタムクラスを設定すると、必要なリンクが提供されると思います。

registerNib()の使用-動作

ペン先による登録は機能します。これは、ビューを明示的にロードしているため意味があります。

let nib = UINib(nibName: "MyCollectionViewCell", bundle: nil)
collectionView?.registerNib(nib, forCellWithReuseIdentifier: "myCell")

ここでは、ビューが明示的に参照され、カスタムクラスがビューに設定されています。しかし、これについて何かが間違っているようです。

サンプルプロジェクト

サンプルプロジェクトで問題を切り分けます。以下は、複製するビューとコードです。または、このプロジェクトは GitHubで入手可能 です。

Main.storyboard

私のメインストーリーボードの初期ビューコントローラーは、UICollectionViewControllerとしてサブクラス化されたMyCollectionViewControllerです。

UICollectionViewController

MyCollectionViewController.Swift

ペン先別とクラス別の両方の登録を表示します。

import UIKit

class MyCollectionViewController: UICollectionViewController {

    var data = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

        data = ["a", "b", "c"]

        // This works, by nib
        let nib = UINib(nibName: "MyCollectionViewCell", bundle: nil)
        collectionView?.registerNib(nib, forCellWithReuseIdentifier: "myCell")

        // This fails, by class
        //collectionView?.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "myCell")
    }

    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return data.count
    }

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! MyCollectionViewCell

        cell.title.text = data[indexPath.row]

        return cell
    }

}

MyCollectionViewCell.xib

ビューはUICollectionViewCellとしてMyCollectionViewCellとしてサブクラス化されたUILabelです。

MyCollectionViewCell

私のペン先では、Collection Reusable View Identifierが次のように設定されています:myCell

MyCollectionViewCell-identifier

MyCollectionViewCell.Swift

クラスを定義し、ラベルにIBOutletを付けます。

import UIKit

class MyCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var title: UILabel!

}

ペン先を使用すると、実行は次のように表示されます。

iphone-4s

クラスごとにUICollectionViewCellを登録できないのはなぜですか?

また、プロトタイプセルをメインのストーリーボードコレクションビューコントローラーに残す必要があるかどうかについても、少しあいまいです。そこでは、再利用可能なビュー識別子を定義していません。

12
Jason Sturges

このリンクが表示されます 概要コレクションビュー

セルクラスがコードで記述されている場合、登録はUICollectionViewのregisterClass:メソッドを使用して実行されます。例:[self.myCollectionView registerClass:[MyCollectionViewCell class] forCellWithReuseIdentifier:@ "MYCELL"];セルがInterfaceBuilder NIBファイル内に含まれている場合は、代わりにregisterNib:メソッドが使用されます。

したがって、コレクションセルはnibで作成するため、nibに登録する必要があります。セルが完全にコードで記述されている場合は、クラスに登録する必要があります。

この助けを願っています。

17
vien vu

実際、ストーリーボードにクラスを登録し、そこで再利用識別子を指定する場合、そのクラスを登録するべきではありませんまたはコードのペン先です。

2
pbush25

nibファイルからセルを定義すると、システムはnibファイルを選択してセルをインスタンス化します。 nibファイルを定義しない場合(完全にコードで維持)、セルはによって初期化される必要があります

- initWithStyle:reuseIdentifier:

方法。使用する場合

- dequeueReusableCellWithIdentifier:

メソッド- awakeFromNibビューを維持するためにnibを使用すると呼び出されます。そうしないと

- initWithStyle:reuseIdentifier:

と呼ばれます。

1
musixlemon

ここで失敗しているのはcollectionviewではありません。カスタムクラスには、このように定義されたオプションで暗黙的にアンラップされたラベルが含まれています。

@IBOutlet weak var title: UILabel!

そしてそれが失敗の理由です。どこでインスタンス化しますか?そして、次のようなデータソースメソッドが呼び出されます。

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! MyCollectionViewCell

    cell.title.text = data[indexPath.row]

    return cell
}

そこで、このプロパティにテキストを設定しようとしていますtitleこれはnilであり、アプリをクラッシュさせます。

修正が必要なコードでラベルを使用する場合は、collectionView initWithFrame:メソッド内でラベルを初期化します。

コードで使用する場合は、このコードをセルサブクラスに追加します。

class MyCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var title: UILabel!

    override init(frame: CGRect) {
        super.init(frame: frame)
        let title = UILabel(frame: CGRectZero)
        title.translatesAutoresizingMaskIntoConstraints = false;
        contentView.addSubview(title)
        self.title = title

        title.topAnchor.constraintEqualToAnchor(contentView.topAnchor).active = true
        title.leftAnchor.constraintEqualToAnchor(contentView.leftAnchor).active = true
        self.backgroundColor = UIColor.redColor()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}
1
Sandeep