web-dev-qa-db-ja.com

XibファイルからカスタムUITableViewCellsをどのようにロードしますか?

問題は簡単です。XibファイルからどのようにカスタムUITableViewCellを読み込むのですか?そうすることで、Interface Builderを使ってセルを設計することができます。答えは明らかにメモリ管理の問題のために単純ではありません。 このスレッド この問題について言及しており、解決策を提案していますが、NDAリリース前であり、コードが欠けています。これが 長いスレッド です。これは明確な答えを提供せずに問題を議論します。

これが私が使ったいくつかのコードです:

static NSString *CellIdentifier = @"MyCellIdentifier";

MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
    cell = (MyCell *)[nib objectAtIndex:0];
}

このコードを使用するには、MyCell.m/.h(UITableViewCellの新しいサブクラス)を作成し、必要なコンポーネントにIBOutletsを追加します。それから新しい "Empty XIB"ファイルを作成してください。 IBでXibファイルを開き、UITableViewCellオブジェクトを追加し、その識別子を "MyCellIdentifier"に設定し、そのクラスをMyCellに設定してコンポーネントを追加します。最後にIBOutletsをコンポーネントに接続します。ファイル所有者をIBに設定しなかったことに注意してください。

他の方法では、ファイルの所有者の設定を推奨し、Xibが追加のファクトリクラスを介してロードされていない場合にメモリリークを警告します。私はInstruments/Leaksの下で上記をテストしました、そしてメモリリークがないことを見ました。

では、Xibからセルをロードするための標準的な方法は何ですか? File's Ownerを設定しますか?工場が必要ですか?もしそうなら、工場のコードはどのようなものですか?複数の解決策がある場合は、それぞれの長所と短所を明確にしましょう。

288
DrGary

これは 元の作者はIBエンジニアによって推奨されたと述べている という2つの方法です。

詳細については実際の記事を参照してください。私は方法2がより簡単に見えるので好む。

方法#1:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Create a temporary UIViewController to instantiate the custom cell.
        UIViewController *temporaryController = [[UIViewController alloc] initWithNibName:@"BDCustomCell" bundle:nil];
        // Grab a pointer to the custom cell.
        cell = (BDCustomCell *)temporaryController.view;
        [[cell retain] autorelease];
        // Release the temporary UIViewController.
        [temporaryController release];
    }

    return cell;
}

方法#2:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Load the top-level objects from the custom cell XIB.
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BDCustomCell" owner:self options:nil];
        // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
        cell = [topLevelObjects objectAtIndex:0];
    }

    return cell;
}

更新(2014):方法#2はまだ有効ですが、それに関する文書はもうありません。以前は 公式ドキュメント に含まれていましたが、今ではストーリーボードのために削除されています。

実例をGithubに投稿しました。
https://github.com/bentford/NibTableCellExample

Swift 4.2用に編集

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    self.tblContacts.register(UINib(nibName: CellNames.ContactsCell, bundle: nil), forCellReuseIdentifier: MyIdentifier)
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: MyIdentifier, for: indexPath) as! ContactsCell

    return cell
}
287
bentford

正しい解決策はこれです:

- (void)viewDidLoad
{
    [super viewDidLoad];
    UINib *nib = [UINib nibWithNibName:@"ItemCell" bundle:nil];
    [[self tableView] registerNib:nib forCellReuseIdentifier:@"ItemCell"];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Create an instance of ItemCell
    PointsItemCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ItemCell"];

    return cell;
}
299
giuseppe

登録

IOS 7以降、このプロセスは(Swift 3.)に簡素化されました:

// For registering nib files
tableView.register(UINib(nibName: "MyCell", bundle: Bundle.main), forCellReuseIdentifier: "cell")

// For registering classes
tableView.register(MyCellClass.self, forCellReuseIdentifier: "cell")

)これは、.xibまたは.stroyboardファイルにセルをプロトタイプセルとして作成することでも実現できます。クラスをクラスにアタッチする必要がある場合は、セルプロトタイプを選択して、対応するクラスを追加できます(もちろんUITableViewCellの子孫でなければなりません)。

デキュー

その後、(Swift 3.)を使用してデキューされました:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    cell.textLabel?.text = "Hello"

    return cell
}

違いは、この新しいメソッドはセルをデキューするだけでなく、存在しない場合にも作成され(if (cell == nil) shenanigansを実行する必要がないことを意味します)、セルは上記の例。

警告tableView.dequeueReusableCell(withIdentifier:for:)には新しい動作があり、もう1つを呼び出すと(indexPath:なしで)古い動作になり、nilとインスタンスを確認する必要があります自分でUITableViewCell?の戻り値に注意してください。

if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? MyCellClass
{
    // Cell be casted properly
    cell.myCustomProperty = true
}
else
{
    // Wrong type? Wrong identifier?
}

そしてもちろん、関連するセルのクラスのタイプは、UITableViewCellサブクラスの.xibファイルで定義したもの、または他のregisterメソッドを使用したものです。

構成

理想的には、セルは登録時までに外観とコンテンツの配置(ラベルや画像ビューなど)に関してすでに構成されており、cellForRowAtIndexPathメソッドでは単純に入力するだけです。

すべて一緒に

class MyCell : UITableViewCell
{
    // Can be either created manually, or loaded from a nib with prototypes
    @IBOutlet weak var labelSomething : UILabel? = nil
}

class MasterViewController: UITableViewController 
{
    var data = ["Hello", "World", "Kinda", "Cliche", "Though"]

    // Register
    override func viewDidLoad()
    {
        super.viewDidLoad()

        tableView.register(MyCell.self, forCellReuseIdentifier: "mycell")
        // or the nib alternative
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return data.count
    }

    // Dequeue
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "mycell", for: indexPath) as! MyCell

        cell.labelSomething?.text = data[indexPath.row]

        return cell
    }
}

そしてもちろん、これはすべて同じ名前のObjCで利用可能です。

38
Can

Shawn Craverの答えを取り、少しそれを片付けた。

BBCell.h:

#import <UIKit/UIKit.h>

@interface BBCell : UITableViewCell {
}

+ (BBCell *)cellFromNibNamed:(NSString *)nibName;

@end

BBCell.m:

#import "BBCell.h"

@implementation BBCell

+ (BBCell *)cellFromNibNamed:(NSString *)nibName {
    NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:NULL];
    NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
    BBCell *customCell = nil;
    NSObject* nibItem = nil;
    while ((nibItem = [nibEnumerator nextObject]) != nil) {
        if ([nibItem isKindOfClass:[BBCell class]]) {
            customCell = (BBCell *)nibItem;
            break; // we have a winner
        }
    }
    return customCell;
}

@end

私はUITableViewCellのすべてのBBCellのサブクラスを作り、それから標準を置き換えます。

cell = [[[BBDetailCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"BBDetailCell"] autorelease];

と:

cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];
33
vilcsak

私はbentfordのを使った方法#2

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BDCustomCell"];
    if (cell == nil) {
        // Load the top-level objects from the custom cell XIB.
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"BDCustomCell" owner:self options:nil];
        // Grab a pointer to the first object (presumably the custom cell, as that's all the XIB should contain).
        cell = [topLevelObjects objectAtIndex:0];
    }

    return cell;
}

動作しますが、カスタムUITableViewCell .xibファイルのファイルの所有者への接続には注意してください。

loadNibNamedステートメントにowner:selfを渡すことで、UITableViewControllerUITableViewCellのファイルの所有者として設定します。

アクションとアウトレットを設定するためにIBのヘッダファイルにドラッグアンドドロップすると、デフォルトでそれらがFile's Ownerとして設定されます。

loadNibNamed:owner:optionsでは、AppleのコードがあなたのUITableViewControllerにプロパティを設定しようとします。しかし、そこにそれらのプロパティが定義されていないので、キー値コーディングに準拠しているというエラーが出ます。

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason:     '[<MyUITableViewController 0x6a383b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key myLabel.'

代わりにイベントが発生すると、NSInvalidArgumentExceptionが発生します。

-[MyUITableViewController switchValueDidChange:]: unrecognized selector sent to instance 0x8e9acd0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyUITableViewController switchValueDidChange:]: unrecognized selector sent to instance 0x8e9acd0'
*** First throw call stack:
(0x1903052 0x15eed0a 0x1904ced 0x1869f00 0x1869ce2 0x1904ec9 0x5885c2 0x58855a 0x62db76 0x62e03f 0x77fa6c 0x24e86d 0x18d7966 0x18d7407 0x183a7c0 0x1839db4 0x1839ccb 0x1f8b879 0x1f8b93e 0x585a9b 0xb904d 0x2c75)
terminate called throwing an exceptionCurrent language:  auto; currently objective-c

簡単な回避策は、Interface Builderの接続をファイルの所有者ではなくUITableViewCellに向けることです。

  1. File's Ownerを右クリックして接続のリストを引き上げる
  2. Command + Shift + 4でスクリーンキャプチャする(ドラッグしてキャプチャする領域を選択する)
  3. file's Ownerからの接続を無効にする
  4. オブジェクト階層のUITableCellを右クリックして接続を再追加します。
16
funroll

私はこれらの答えのどれもが好きではないので投稿することにしました - 物事はいつもより単純でありえます、そしてこれは私が見つけたはるかに最も簡潔な方法です。

1.あなたが好きなようにInterface BuilderでXibをビルドしてください

  • ファイルの所有者をクラスNSObjectに設定します。
  • UITableViewCellを追加し、そのクラスをMyTableViewCellSubclassに設定します - あなたのIBがクラッシュした場合(この記事の執筆時点ではXcode> 4で発生します)、まだUIViewを使用している場合はXcode 4でインターフェースを実行してください。
  • このセル内にサブビューをレイアウトし、IBOutlet接続を.hまたは.m(.mが私の好みです)の@interfaceに添付します。

2。あなたのUIViewControllerまたはUITableViewControllerサブクラスで

@implementation ViewController

static NSString *cellIdentifier = @"MyCellIdentier";

- (void) viewDidLoad {

    ...
    [self.tableView registerNib:[UINib nibWithNibName:@"MyTableViewCellSubclass" bundle:nil] forCellReuseIdentifier:cellIdentifier];
}

- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    MyTableViewCellSubclass *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    ...

    return cell;
}

。MyTableViewCellSubクラス内

- (id) initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        ...
    }

    return self;
}
14
webstersx

Interface Builderを使ってセルを作成している場合は、インスペクタでIdentifierを設定したことを確認してください。次に、dequeueReusableCellWithIdentifierを呼び出したときと同じであることを確認してください。

私は誤ってテーブルを多用するプロジェクトでいくつかの識別子を設定するのを忘れていました、そしてパフォーマンスの変化は昼と夜のようでした。

9
Alex R. Young

XIBからUITableViewCellsをロードすると、多くのコードを節約できますが、通常はスクロール速度が非常に遅くなります(実際、これはXIBではなく、UIViewを過度に使用するためです)。

これを見てみることをお勧めします: リンク参照

8
Can Berk Güder

XIBからカスタムセルを作成するために使用しているクラスメソッドは次のとおりです。

+ (CustomCell*) createNewCustomCellFromNib {

    NSArray* nibContents = [[NSBundle mainBundle]
                            loadNibNamed:@"CustomCell" owner:self options:NULL];

    NSEnumerator *nibEnumerator = [nibContents objectEnumerator];
    CustomCell *customCell= nil;
    NSObject* nibItem = nil;

    while ( (nibItem = [nibEnumerator nextObject]) != nil) {

        if ( [nibItem isKindOfClass: [CustomCell class]]) {
            customCell = (CustomCell*) nibItem;

            if ([customCell.reuseIdentifier isEqualToString: @"CustomCell"]) {
                break; // we have a winner
            }
            else
                fuelEntryCell = nil;
        }
    }
    return customCell;
}

次に、XIBでクラス名を設定し、識別子を再利用します。その後、私のView Controllerでそのメソッドを呼び出すだけで済みます。

[[UITableViewCell] alloc] initWithFrame:]

それは十分に速く、そして私の2つの出荷アプリケーションで使われています。これは[nib objectAtIndex:0]を呼び出すよりも信頼性が高く、少なくとも私の考えではStephan Burlotの例より信頼性が高いのは、正しいタイプのXIBからビューを取得することだけが保証されているからです。

6
Shawn Craver

正しい解決策はこちら

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.tableView registerNib:[UINib nibWithNibName:@"CustomCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"CustomCell"];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell  *cell = [tableView dequeueReusableCellWithIdentifier:@"CustomCell"];
    return cell; 
    }
5
Hamiz Ahmed

これをチェックしてください--- http://eppz.eu/blog/custom-uitableview-cell/ - コントローラ実装の1行になってしまう小さなクラスを使った本当に便利な方法です。

-(UITableViewCell*)tableView:(UITableView*) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath
{
    return [TCItemCell cellForTableView:tableView
                          atIndexPath:indexPath
                      withModelSource:self];
}

enter image description here

4
Geri

NIBをリロードするのは高価です。一度ロードしてから、セルが必要になったときにオブジェクトをインスタンス化してください。このメソッドを使用すると、UIImageViewsなどをnibに、複数のセルにも追加できることに注意してください(Appleの "registerNIB" iOS 5では1つの最上位オブジェクトしか許可されません - バグ10580062 "iOS 5 tableView registerNib:過度に制限的"

だから私のコードは以下の通りです - あなたは一度NIBを読んだ(私がやったように初期化してもviewDidloadも - 何でも。その後、あなたはオブジェクトにペン先をインスタンス化し、必要なものを選びます。これはペン先をロードするよりはるかに効率的です。何度も。

static UINib *cellNib;

+ (void)initialize
{
    if(self == [ImageManager class]) {
        cellNib = [UINib nibWithNibName:@"ImageManagerCell" bundle:nil];
        assert(cellNib);
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellID = @"TheCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if(cell == nil) {
        NSArray *topLevelItems = [cellNib instantiateWithOwner:nil options:nil];
        NSUInteger idx = [topLevelItems indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop)
                            {
                                UITableViewCell *cell = (UITableViewCell *)obj;
                                return [cell isKindOfClass:[UITableViewCell class]] && [cell.reuseIdentifier isEqualToString:cellID];
                            } ];
        assert(idx != NSNotFound);
        cell = [topLevelItems objectAtIndex:idx];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"Howdie %d", indexPath.row];

    return cell;
}
4
David H

その正しい方法は、UITableViewCellサブクラスの実装、ヘッダー、およびXIBを作成することです。 XIBでビューを削除して、テーブルセルを追加するだけです。クラスをUITableViewCellサブクラスの名前として設定します。ファイルの所有者の場合は、それをUITableViewControllerサブクラスクラス名にします。 tableViewCellアウトレットを使用して、ファイルの所有者をセルに接続します。

ヘッダファイルで:

UITableViewCell *_tableViewCell;
@property (assign) IBOutlet UITableViewCell *tableViewCell;

実装ファイルでは、

@synthesize tableViewCell = _tableViewCell;

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *kCellIdentifier = @"reusableCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
    if (cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:kCellIdentifier owner:self options:nil];
        cell = _tableViewCell;
        self.tableViewCell = nil;
    }

    return cell;
}

そのために私がすることはあなたのコントローラクラスでIBOutlet UITableViewCell *cellを宣言することです。それからNSBundle loadNibNamedクラスメソッドを呼び出します。これはUITableViewCellを上で宣言されたセルに供給します。

Xibの場合は、空のxibを作成し、必要に応じて設定できるIBにUITableViewCellオブジェクトを追加します。このビューは、コントローラクラスのセルIBOutletに接続されています。

- (UITableViewCell *)tableView:(UITableView *)table
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"%@ loading RTEditableCell.xib", [self description] );

    static NSString *MyIdentifier = @"editableCellIdentifier";
    cell = [table dequeueReusableCellWithIdentifier:MyIdentifier];

    if(cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:@"RTEditableCell"
                                      owner:self
                                    options:nil];
    }

    return cell;
}

NSBundleの追加loadNibNamed(ADCログイン)

cocoawithlove.comの記事から概念を入手しました(電話番号のサンプルアプリを入手)

3
Ryan Townshend

最初にカスタムセルファイル#import "CustomCell.h"をインポートしてから、次に説明するようにデリゲートメソッドを変更します。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *simpleTableIdentifier = @"CustomCell";

CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
    cell = [nib objectAtIndex:0];

    [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}         

     return cell;
}
2
Mohit
  1. AbcViewCellから独自のカスタマイズクラスUITableViewCellサブクラスを作成します(クラスファイル名とnibファイル名が同じであることを確認してください)。

  2. この拡張クラスメソッドを作成します。

    extension UITableViewCell {
        class func fromNib<T : UITableViewCell>() -> T {
            return Bundle.main.loadNibNamed(String(describing: T.self), owner: nil, options: nil)?[0] as! T
        }
    }
    
  3. これを使って。

    let cell: AbcViewCell = UITableViewCell.fromNib()

2
William Hu

これはUITableViewにセルを登録するための普遍的なアプローチです。

protocol Reusable {
    static var reuseID: String { get }
}

extension Reusable {
    static var reuseID: String {
        return String(describing: self)
    }
}

extension UITableViewCell: Reusable { }

extension UITableView {

func register<T: UITableViewCell>(cellClass: T.Type = T.self) {
    let bundle = Bundle(for: cellClass.self)
    if bundle.path(forResource: cellClass.reuseID, ofType: "nib") != nil {
        let nib = UINib(nibName: cellClass.reuseID, bundle: bundle)
        register(nib, forCellReuseIdentifier: cellClass.reuseID)
    } else {
        register(cellClass.self, forCellReuseIdentifier: cellClass.reuseID)
    }
}

説明:

  1. Reusableプロトコルはそのクラス名からセルIDを生成します。必ずcell ID == class name == nib nameの規則に従ってください。
  2. UITableViewCellReusableプロトコルに準拠しています。
  3. UITableView拡張子は、nibまたはクラスを介してセルを登録する際の違いを抽象化します。

使用例

override func viewDidLoad() {
    super.viewDidLoad()
    let tableView = UITableView()
    let cellClasses: [UITableViewCell.Type] = [PostCell.self, ProfileCell.self, CommentCell.self]
    cellClasses.forEach(tableView.register)
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: PostCell.self.reuseID) as? PostCell
    ...
    return cell
}
1
Vadim Bulavin

In Swift 4.2 and Xcode 10

XIBセルファイルが3つあります

viewDidLoadでこのようにXIBファイルを登録してください...

これが最初のアプローチです

tableView.register(UINib.init(nibName: "XIBCell", bundle: nil), forCellReuseIdentifier: "cell1")
tableView.register(UINib.init(nibName: "XIBCell2", bundle: nil), forCellReuseIdentifier: "cell2")
//tableView.register(UINib.init(nibName: "XIBCell3", bundle: nil), forCellReuseIdentifier: "cell3")

2番目の方法は、XIBファイルを直接---に登録するcellForRowAt indexPath:

これは私のテーブルビューデリゲート関数です

//MARK: - Tableview delegates
override func numberOfSections(in tableView: UITableView) -> Int {

    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return 6
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //This is first approach
    if indexPath.row == 0 {//Load first XIB cell
        let placeCell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! XIBCell
        return placeCell
    //Second approach
    } else if indexPath.row == 5 {//Load XIB cell3
        var cell = tableView.dequeueReusableCell(withIdentifier:"cell3") as? XIBCell3
        if cell == nil{
            let arrNib:Array = Bundle.main.loadNibNamed("XIBCell3",owner: self, options: nil)!
            cell = arrNib.first as? XIBCell3
        }

        //ADD action to XIB cell button
        cell?.btn.tag = indexPath.row//Add tag to button
        cell?.btn.addTarget(self, action: #selector(self.bookbtn1(_:)), for: .touchUpInside);//selector

        return cell!
    //This is first approach
    } else {//Load XIB cell2
        let placeCell = tableView.dequeueReusableCell(withIdentifier: "cell2") as! XIBCell2

        return placeCell
    }

}
1
iOS

これがそのための私の方法です: XIBファイルからカスタムUITableViewCellを読み込む…さらに別の方法

アイデアは、IBOutlet UIView *contentプロパティと、コードから構成する必要がある各カスタムサブビューのプロパティを持つUITableViewCellのSampleCellサブクラスを作成することです。次にSampleCell.xibファイルを作成します。このnibファイルで、ファイルの所有者をSampleCellに変更します。ニーズに合わせたサイズのコンテンツUIViewを追加します。必要なすべてのサブビュー(ラベル、画像ビュー、ボタンなど)を追加して構成します。最後に、コンテンツビューとサブビューをファイルの所有者にリンクします。

1
MonsieurDart

標準的な方法があるかどうか私は知りませんが、これが私の方法です:

  • ViewController用のxibを作成する
  • File OwnerクラスをUIViewControllerに設定します。
  • ビューを削除してUITableViewCellを追加します
  • UITableViewCellのクラスをカスタムクラスに設定します。
  • UITableViewCellの識別子を設定します
  • View ControllerビューのアウトレットをUITableViewCellに設定します。

そして、このコードを使用してください:

MyCustomViewCell *cell = (MyCustomViewCell *)[_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
  UIViewController* c = [[UIViewController alloc] initWithNibName:CellIdentifier bundle:nil];
  cell = (MyCustomViewCell *)c.view;
  [c release];
}

あなたの例では、

[nib objectAtIndex:0]

appleがxib内の項目の順序を変更すると、壊れる可能性があります。

0
Stephan Burlot
 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

            let cellReuseIdentifier = "collabCell"
            var cell:collabCell! = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as? collabCell
            if cell == nil {
                tableView.register(UINib(nibName: "collabCell", bundle: nil), forCellReuseIdentifier: cellReuseIdentifier)
                cell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! collabCell!
            }


            return cell

}
0
Hitesh Chauhan

この拡張機能にはXcode 7 beta 6が必要です

extension NSBundle {
    enum LoadViewError: ErrorType {
        case ExpectedXibToExistButGotNil
        case ExpectedXibToContainJustOneButGotDifferentNumberOfObjects
        case XibReturnedWrongType
    }

    func loadView<T>(name: String) throws -> T {
        let topLevelObjects: [AnyObject]! = loadNibNamed(name, owner: self, options: nil)
        if topLevelObjects == nil {
            throw LoadViewError.ExpectedXibToExistButGotNil
        }
        if topLevelObjects.count != 1 {
            throw LoadViewError.ExpectedXibToContainJustOneButGotDifferentNumberOfObjects
        }
        let firstObject: AnyObject! = topLevelObjects.first
        guard let result = firstObject as? T else {
            throw LoadViewError.XibReturnedWrongType
        }
        return result
    }
}

カスタムUITableViewCellを1つだけ含むXibファイルを作成します。

それをロードしてください。

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")
0
neoneye
 NSString *CellIdentifier = [NSString stringWithFormat:@"cell %ld %ld",(long)indexPath.row,(long)indexPath.section];


    NewsFeedCell *cell = (NewsFeedCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    cell=nil;

    if (cell == nil)
    {
        NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NewsFeedCell" owner:nil options:nil];

        for(id currentObject in topLevelObjects)
        {
            if([currentObject isKindOfClass:[NewsFeedCell class]])
            {
                cell = (NewsFeedCell *)currentObject;
                break;
            }
        }
}
return cell;
0
2014