我有一个带有UITableViewxib文件,我想使用委托方法tableView:viewForHeaderInSection:为其添加一个自定义的节头视图.有没有可能在Interface Builder中设计它,然后以编程方式更改它的一些子视图属性?

我的UITableView有更多的节头,所以在Interface Builder中创建一个UIView并返回它是不起作用的,因为我必须复制它,但没有任何好的方法来做它.归档和取消归档它对UIImage不起作用,所以UIImageView会显示为空白.

此外,我不想以编程的方式创建它们,因为它们太复杂,生成的代码很难读取和维护.

Edit 1:以下是我的tableView:viewForHeaderInSection:种方法:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return nil;
    }

    CGSize headerSize = CGSizeMake(self.view.frame.size.width, 100);

    /* wrapper */

    UIView *wrapperView = [UIView viewWithSize:headerSize];

    wrapperView.backgroundColor = [UIColor colorWithHexString:@"2670ce"];

    /* title */

    CGPoint titleMargin = CGPointMake(15, 8);

    UILabel *titleLabel = [UILabel labelWithText:self.categoriesNames[section] andFrame:CGEasyRectMake(titleMargin, CGSizeMake(headerSize.width - titleMargin.x * 2, 20))];

    titleLabel.textColor = [UIColor whiteColor];
    titleLabel.font = [UIFont fontWithStyle:FontStyleRegular andSize:14];

    [wrapperView addSubview:titleLabel];

    /* body wrapper */

    CGPoint bodyWrapperMargin = CGPointMake(10, 8);

    CGPoint bodyWrapperViewOrigin = CGPointMake(bodyWrapperMargin.x, CGRectGetMaxY(titleLabel.frame) + bodyWrapperMargin.y);
    CGSize bodyWrapperViewSize = CGSizeMake(headerSize.width - bodyWrapperMargin.x * 2, headerSize.height - bodyWrapperViewOrigin.y - bodyWrapperMargin.y);

    UIView *bodyWrapperView = [UIView viewWithFrame:CGEasyRectMake(bodyWrapperViewOrigin, bodyWrapperViewSize)];

    [wrapperView addSubview:bodyWrapperView];

    /* image */

    NSInteger imageSize = 56;
    NSString *imageName = [self getCategoryResourceItem:section + 1][@"image"];

    UIImageView *imageView = [UIImageView imageViewWithImage:[UIImage imageNamed:imageName] andFrame:CGEasyRectMake(CGPointZero, CGEqualSizeMake(imageSize))];

    imageView.layer.masksToBounds = YES;
    imageView.layer.cornerRadius = imageSize / 2;

    [bodyWrapperView addSubview:imageView];

    /* labels */

    NSInteger labelsWidth = 60;

    UILabel *firstLabel = [UILabel labelWithText:@"first" andFrame:CGRectMake(imageSize + bodyWrapperMargin.x, 0, labelsWidth, 16)];

    [bodyWrapperView addSubview:firstLabel];

    UILabel *secondLabel = [UILabel labelWithText:@"second" andFrame:CGRectMake(imageSize + bodyWrapperMargin.x, 20, labelsWidth, 16)];

    [bodyWrapperView addSubview:secondLabel];

    UILabel *thirdLabel = [UILabel labelWithText:@"third" andFrame:CGRectMake(imageSize + bodyWrapperMargin.x, 40, labelsWidth, 16)];

    [bodyWrapperView addSubview:thirdLabel];

    [@[ firstLabel, secondLabel, thirdLabel ] forEachView:^(UIView *view) {
        UILabel *label = (UILabel *)view;

        label.textColor = [UIColor whiteColor];
        label.font = [UIFont fontWithStyle:FontStyleLight andSize:11];
    }];

    /* line */

    UIView *lineView = [UIView viewWithFrame:CGRectMake(imageSize + labelsWidth + bodyWrapperMargin.x * 2, bodyWrapperMargin.y, 1, bodyWrapperView.frame.size.height - bodyWrapperMargin.y * 2)];

    lineView.backgroundColor = [UIColor whiteColorWithAlpha:0.2];

    [bodyWrapperView addSubview:lineView];

    /* progress */

    CGPoint progressSliderOrigin = CGPointMake(imageSize + labelsWidth + bodyWrapperMargin.x * 3 + 1, bodyWrapperView.frame.size.height / 2 - 15);
    CGSize progressSliderSize = CGSizeMake(bodyWrapperViewSize.width - bodyWrapperMargin.x - progressSliderOrigin.x, 30);

    UISlider *progressSlider = [UISlider viewWithFrame:CGEasyRectMake(progressSliderOrigin, progressSliderSize)];

    progressSlider.value = [self getCategoryProgress];

    [bodyWrapperView addSubview:progressSlider];

    return wrapperView;
}

我希望它看起来像这样:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return nil;
    }

    SectionView *sectionView = ... // get the view that is already designed in the Interface Builder

    sectionView.headerText = self.categoriesNames[section];
    sectionView.headerImage = [self getCategoryResourceItem:section + 1][@"image"];

    sectionView.firstLabelText = @"first";
    sectionView.secondLabelText = @"second";
    sectionView.thirdLabelText = @"third";

    sectionView.progress = [self getCategoryProgress];

    return wrapperView;
}

Edit 2:我用的不是Storyboard,而是.xib个文件.此外,我没有UITableViewController,只有UIViewController,其中我加了UITableView.

推荐答案

我最终用this tutorial解决了这个问题,它主要由以下(adapted to my example)个部分组成:

  1. 创建SectionHeaderView个子类UIView的类.
  2. 创建SectionHeaderView.xib个文件,并将其设置为File's OwnerCustomClassSectionHeaderView类.
  3. .m文件中创建一个UIView属性,如:@property (strong, nonatomic) IBOutlet UIView *viewContent;
  4. .xib's View连接到这个viewContent插座.
  5. 添加如下所示的初始值设定项方法:

    + (instancetype)header {
    
        SectionHeaderView *sectionHeaderView = [[SectionHeaderView alloc] init];
    
        if (sectionHeaderView) { // important part
            sectionHeaderView.viewContent = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:sectionHeaderView options:nil] firstObject];
    
            [sectionHeaderView addSubview:sectionHeaderView.viewContent];
    
            return sectionHeaderView;
        }
    
        return nil;
    }
    

然后,我在.xib文件中添加了一个UILabel,并将其连接到labelCategoryName插座,并在SectionHeaderView类中实现了setCategoryName:方法,如下所示:

- (void)setCategoryName:(NSString *)categoryName {

    self.labelCategoryName.text = categoryName;
}

然后我实现了tableView:viewForHeaderInSection:方法,如下所示:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    SectionHeaderView *sectionHeaderView = [SectionHeaderView header];

    [sectionHeaderView setCategoryName:self.categoriesNames[section]];

    return sectionHeaderView;
}

它终于成功了.每个部分都有自己的名称,而且UIImageView个部分也会正确地显示出来.

希望它能帮助那些像我一样在网络上一次又一次地遇到同样错误解决方案的人.

Objective-c相关问答推荐

恢复 iOS7 之前的 UINavigationController pushViewController 动画

跨平台 iPhone/Android 代码共享

如何从 C 方法调用 Objective-C 方法?

多个(两个)持久存储可以与一个对象模型一起使用,同时保持一个到另一个的关系吗?

将 Objective-C 指针类型NSString *转换为 C 指针类型CFStringRef(又名const struct __CFString *)需要桥接转换

将 CSS 插入 UIWebView / WKWebView 中加载的 HTML

iOS:将 URL 解析为段

使用 UIViewControllerInteractiveTransitioning 委托协议实现自定义 UIViewController 交互式过渡的正确方法

当单元格全屏时,为什么 UICollectionView 会记录错误?

iOS 6 Facebook 发布过程以remote_app_id 与存储的 id 不匹配结束

如何从 CGPoint 和 CGSize 创建 CGRect?

在 NSNumbers 的 NSArray 中查找最小值和最大值

Objective-C 异常

如何在 Objective-C 中添加具有自己的 UIViewController 的子视图?

在objective c中以自定义格式获取当前时间

UIImageView 并不总是为模板图像着色

iPhone如何在打字时获取UITextField的文本?

performFetchWithCompletionHandler 永远不会被解雇

捕捉固定步数的 UISlider(如 iOS 7 设置应用程序中的文本大小)

Xcode 如何加载主情节提要?