How do you load custom UITableViewCells from Xib files?

前端 未结 23 1728
抹茶落季
抹茶落季 2020-11-22 11:11

The question is simple: How do you load custom UITableViewCell from Xib files? Doing so allows you to use Interface Builder to design your cells. The answer app

相关标签:
23条回答
  • 2020-11-22 11:17
     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 讨论(0)
  • 2020-11-22 11:18

    What I do for this is declare an IBOutlet UITableViewCell *cell in your controller class. Then invoke the NSBundle loadNibNamed class method, which will feed the UITableViewCell to the cell declared above.

    For the xib I will create an empty xib and add the UITableViewCell object in IB where it can be setup as needed. This view is then connected to the cell IBOutlet in the controller class.

    - (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 additions loadNibNamed (ADC login)

    cocoawithlove.com article I sourced the concept from (get the phone numbers sample app)

    0 讨论(0)
  • 2020-11-22 11:19

    Took Shawn Craver's answer and cleaned it up a bit.

    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
    

    I make all my UITableViewCell's subclasses of BBCell, and then replace the standard

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

    with:

    cell = (BBDetailCell *)[BBDetailCell cellFromNibNamed:@"BBDetailCell"];
    
    0 讨论(0)
  • 2020-11-22 11:20

    Check this - http://eppz.eu/blog/custom-uitableview-cell/ - really convenient way using a tiny class that ends up one line in controller implementation:

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

    enter image description here

    0 讨论(0)
  • 2020-11-22 11:21

    Here's the class method that I've been using for creating custom cells out of XIBs:

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

    Then, in the XIB, I set the class name, and reuse identifier. After that, I can just call that method in my view controller instead of the

    [[UITableViewCell] alloc] initWithFrame:]
    

    It's plenty fast enough, and being used in two of my shipping applications. It's more reliable than calling [nib objectAtIndex:0], and in my mind at least, more reliable than Stephan Burlot's example because you're guaranteed to only grab a view out of a XIB that is the right type.

    0 讨论(0)
  • 2020-11-22 11:22

    Here is a universal approach for registering cells in 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)
        }
    }
    

    Explanation:

    1. Reusable protocol generates cell ID from its class name. Make sure you follow the convention: cell ID == class name == nib name.
    2. UITableViewCell conforms to Reusable protocol.
    3. UITableView extension abstracts away the difference in registering cells via nib or class.

    Usage example:

    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 讨论(0)
提交回复
热议问题