Xib 파일에서 사용자 정의 UITableViewCell을 어떻게로드합니까?


293

문제는 간단합니다. UITableViewCellXib 파일에서 사용자 정의 를 어떻게로드 합니까? 그렇게하면 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오브젝트를 추가 하고 ID를 "MyCellIdentifier"로 설정 한 후 클래스를 MyCell로 설정하고 구성 요소를 추가하십시오. 마지막으로을 IBOutlets구성 요소에 연결하십시오 . IB에서 파일 소유자를 설정하지 않았습니다.

다른 메소드는 파일 소유자 설정을 옹호하고 Xib가 추가 팩토리 클래스를 통해로드되지 않은 경우 메모리 누수에 대해 경고합니다. 위의 Instruments / Leaks에서 테스트했으며 메모리 누수가 없음을 확인했습니다.

Xibs에서 셀을로드하는 정식 방법은 무엇입니까? File 's Owner를 설정합니까? 우리는 공장이 필요합니까? 그렇다면 공장 코드는 어떻게 생겼습니까? 여러 솔루션이있는 경우 각 솔루션의 장단점을 명확히하십시오.


2
"Xib 파일에서 사용자 정의 UITableViewCell을 어떻게로드합니까?" (이것이
Steven Fisher

1
iOS 5 이상의 경우이 솔루션은 stackoverflow.com/questions/15591364/… 이며 이는 주세페의 솔루션과 동일합니다.
Matt Becker

빠른 메모 간단한 (2013 환경) 대답 여기 stackoverflow.com/questions/15378788/... jamihash
Fattie

답변:


288

IB 엔지니어가 원 저자가 추천 한 두 가지 방법은 다음과 같습니다 .

자세한 내용은 실제 게시물을 참조하십시오. 더 간단한 것처럼 방법 # 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

스위프트 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
}

1
방법 1의 경우 "cell = (BDCustomCell *) [[temporaryController.view retain] autorelease];"와 같은 작업을 수행해서는 안됩니다. 임시 컨트롤러를 놓을 때 셀이 해제되지 않습니까?
Tod Cunningham

흠. # 2에 관한 문서는 여전히 XIB 파일의 셀 소유자를 알려진 컨트롤러 클래스로 설정하도록 알려줍니다. 로드하는 동안 소유자를 설정하면 문제가되지 않을 수 있습니다.
Oscar

@OscarGoldman XIB 파일의 셀 소유자는 클래스 (예 : 소유자 유형)입니다. loadNibNamed : owner : options :의 셀 소유자는 XIB에 지정된 유형의 객체입니다.
bentford

2
@CoolDocMan 옵션 # 2는 여전히 작동합니다. 펜촉에 문제가있을 가능성이 높습니다. 예를 들면 다음과 같습니다. github.com/bentford/NibTableCellExample
bentford

2
이 오래된 코드가 왜 그렇게 높은 순위를 차지합니까? Stackoverflow 뭔가를 : /
Nico S.

304

올바른 해결책은 다음과 같습니다.

- (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;
}

iOS5 앱을 깨뜨릴까요? 나는 UINib를 본 적이 없다
Adam Waite

@AdamWaite NIB 파일 등록은 iOS 5 이상에서 작동하므로 iOS 5 앱을 중단하지 않습니다. 그리고 UINib는 iOS 4부터 존재합니다.
Mecki

좋은 예를 보려면 여기에 맨 위 답변에서 참조 된 git repo를 확인하십시오. stackoverflow.com/questions/18746929/…
netigger

39

레지스터

iOS 7 이후이 프로세스는 ( swift 3.0 ) 으로 단순화되었습니다 .

// 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.0 )을 사용하여 대기열에서 제외했습니다 .

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:)에는 새로운 동작이 있습니다. 다른 동작을 호출하면 ()없이 indexPath:기존 동작을 확인할 nilUITableViewCell?있습니다.

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 파일에서 정의한 유형 이거나 다른 레지스터 메소드를 사용하여 정의 된 유형입니다 .

구성

이상적으로는 셀을 등록 할 때의 모양 및 내용 위치 (레이블 및 이미지보기 등)와 셀을 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에서 모두 같은 이름으로 제공됩니다.


objC 버전은 다음과 같습니다.[self.tableView registerNib:[UINib nibWithNibName:@"BlaBlaTableViewCell" bundle:nil] forCellReuseIdentifier:kCellIdentifier];
Zeb

33

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"];

16

나는 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 파일에서 File 's Owner 에 연결 되어 있는지 확인하십시오.

전달하여 owner:self귀하의 loadNibNamed성명, 당신은 설정 UITableViewController당신의 파일의 소유자로 UITableViewCell.

IB의 헤더 파일로 끌어서 놓아 조치 및 아울렛을 설정하면 기본적으로 파일 소유자로 설정됩니다.

에서 loadNibNamed:owner:options, 애플의 코드는에 속성을 설정하려고합니다 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

쉬운 해결 방법은 UITableViewCell파일 소유자 대신 인터페이스 빌더 연결을 지정하는 것입니다.

  1. File 's Owner를 마우스 오른쪽 버튼으로 클릭하여 연결 목록을 불러옵니다.
  2. Command-Shift-4로 화면을 캡처합니다 (끌어서 캡처 할 영역을 선택합니다)
  3. 파일 소유자의 연결을 x
  4. 오브젝트 계층에서 UITableCell을 마우스 오른쪽 단추로 클릭하고 연결을 다시 추가하십시오.

언급 한 문제가 있었지만 File 소유자 대신 UITableViewCell에 연결하는 방법은 무엇입니까? 예를 들어 왜 스크린 샷을 찍어야합니까? 내가 콘센트 옆에있는 추가 버튼을 클릭 할 때 아무 일도 발생하지 않습니다
쑤 huanze

@xuhuanze 스크린 샷을 만들 것을 제안 했으므로 File 소유자가 이미 연결 한 내용을 기록 할 수 있습니다. 그런 다음 동일한 연결을 다시 만들 수 있습니다. 한 번의 클릭 만이 아니라 연결을 추가하려면 끌어서 놓아야합니다.
funroll

고마워요, "이 클래스는 키 값 코딩 키와 호환되지 않습니다"라는 문제가 있었고 여러분의 도움으로 해결했습니다. UITableViewCell의 클래스를 클래스로 변경하고 사용자 정의 셀 클래스로 사용한다고 다른 사람들에게 말하고 싶습니다.
Denis Kutlubaev

14

이 답변 중 어느 것도 마음에 들지 않기 때문에 게시하기로 결정했습니다. 일이 항상 더 간단 할 수 있으며 이것이 내가 찾은 가장 간결한 방법입니다.

1. 원하는대로 Interface Builder에서 Xib를 빌드하십시오.

  • 파일 소유자를 NSObject 클래스로 설정
  • UITableViewCell을 추가하고 클래스를 MyTableViewCellSubclass로 설정하십시오-IB가 충돌하는 경우 (이 글에서 Xcode> 4로 발생) Xcode 4에서 UIView를 사용하십시오.
  • 이 셀 안에 하위 뷰를 배치하고 .h 또는 .m에서 IBOutlet 연결을 @interface에 연결하십시오 (.m이 선호)

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;
}

3. MyTableViewCellSubclass에서

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

    return self;
}

9

Interface Builder를 사용하여 셀을 만드는 경우 Inspector에서 식별자를 설정했는지 확인하십시오. 그런 다음 dequeueReusableCellWithIdentifier를 호출 할 때 동일한 지 확인하십시오.

실수로 테이블이 많은 프로젝트에서 일부 식별자를 설정하는 것을 잊어 버렸고 성능 변경은 밤낮과 같습니다.


8

XIB에서 UITableViewCells를로드하면 많은 코드가 절약되지만 일반적으로 스크롤 속도가 끔찍합니다 (실제로는 XIB가 아니라 UIViews를 과도하게 사용함).

나는 당신이 이것을 볼 것을 제안합니다 : 링크 참조


6

다음은 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에서 클래스 이름을 설정하고 식별자를 재사용합니다. 그런 다음 뷰 컨트롤러에서 해당 메소드를 호출 할 수 있습니다.

[[UITableViewCell] alloc] initWithFrame:]

충분히 빠르며 두 가지 운송 응용 프로그램에서 사용됩니다. 호출하는 것보다 더 안정적이며 [nib objectAtIndex:0], 적어도 내 생각에 Stephan Burlot의 예보다 더 안정적입니다. 올바른 유형의 XIB에서 뷰를 가져 오기만 보장하기 때문입니다.


5

올바른 해결책은 이쪽

- (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; 
    }

4

NIB를 새로 고침하는 것은 비용이 많이 듭니다. 한 번만로드 한 다음 셀이 필요할 때 객체를 인스턴스화하십시오. 이 방법을 사용하여 UIImageViews 등을 nib, 심지어 여러 셀에 추가 할 수 있습니다 (Apple의 "registerNIB"iOS5는 하나의 최상위 객체 만 허용 함)-버그 10580062 "iOS5 tableView registerNib : 지나치게 제한적"

그래서 내 코드는 아래에 있습니다-NIB를 한 번 읽습니다. 계속해서.

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

이것을 확인하십시오 -http : //eppz.eu/blog/custom-uitableview-cell/- 컨트롤러 구현에서 한 줄로 끝나는 작은 클래스를 사용하는 정말 편리한 방법입니다.

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

여기에 이미지 설명을 입력하십시오


3

올바른 방법은 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;
}

3

내가 이것을 위해하는 일은 IBOutlet UITableViewCell *cell컨트롤러 클래스에서를 선언하는 것 입니다. 그런 다음 NSBundle loadNibNamed클래스 메소드를 호출하여 UITableViewCell위에서 선언 한 셀에 피드 를 제공합니다.

xib의 경우 빈 xib를 만들고 UITableViewCellIB에 객체를 추가하여 필요에 따라 설정할 수 있습니다. 그런 다음이보기는 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
  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

먼저 사용자 정의 셀 파일 #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

에서 스위프트 4.2 및 엑스 코드 (10)

세 개의 XIB 셀 파일이 있습니다

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")

두 번째 방법은 cellForRowAt indexPath에 XIB 파일을 직접 등록합니다 .

이것은 내 테이블 뷰 위임 함수입니다.

//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

다음은 그 방법입니다. XIB 파일에서 사용자 정의 UITableViewCells로드 중 ... 또 다른 방법

아이디어는 코드에서 구성해야하는 각 사용자 정의 서브 뷰에 대한 특성과 특성을 UITableViewCell가진 SampleCell 서브 클래스를 작성하는 것입니다 IBOutlet UIView *content. 그런 다음 SampleCell.xib 파일을 작성하십시오. 이 nib 파일에서 파일 소유자를 SampleCell로 변경하십시오. UIView필요에 맞는 크기 의 컨텐츠를 추가하십시오 . 원하는 모든 하위보기 (라벨, 이미지보기, 단추 등)를 추가하고 구성하십시오. 마지막으로 컨텐츠 뷰와 서브 뷰를 파일 소유자에게 연결하십시오.


1

다음에 셀을 등록하는 일반적인 방법은 다음과 같습니다 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. Reusableprotocol은 클래스 이름에서 셀 ID를 생성합니다. 다음 규칙을 준수해야합니다 cell ID == class name == nib name..
  2. UITableViewCellReusable프로토콜을 준수 합니다.
  3. UITableView 확장은 펜촉 또는 클래스를 통해 셀을 등록하는 차이를 추상화합니다.

사용 예 :

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
}

0

정식 방법이 있는지 모르겠지만 여기에 내 방법이 있습니다.

  • ViewController에 대한 xib 생성
  • 파일 소유자 클래스를 UIViewController로 설정하십시오.
  • 뷰를 삭제하고 UITableViewCell을 추가하십시오.
  • UITableViewCell의 클래스를 사용자 정의 클래스로 설정하십시오.
  • UITableViewCell의 식별자를 설정하십시오.
  • 뷰 컨트롤러 뷰의 콘센트를 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의 항목 순서를 변경하면 중단 될 수 있습니다.


나에게 이것은 항상 새로운 인스턴스를 만듭니다. dequeue는 매번 nil을 반환하는 것 같습니다.
이상한

0
 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

이 확장 프로그램에는 Xcode7 beta6이 필요합니다

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이 포함 된 Xib 파일을 작성하십시오.

로드하십시오.

let cell: BacteriaCell = try NSBundle.mainBundle().loadView("BacteriaCell")

0
 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

}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.