You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Objective-C加载自定义Xib关联Outlet触发NSUnknownKeyException报错求助

NSUnknownKeyException 异常修复方案

问题场景与报错信息

开发Objective-C项目时,自定义CollectionViewCell的Xib并关联Outlet后,出现如下崩溃:

2023-06-07 22:50:32.194106-0700 ProturisApp[91070:2437111] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<InputCollectionViewCell 0x10403ee78> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key brickWall.'

相关代码如下:

UIView分类(NIBLoader)

@implementation UIView (NIBLoader)
+ (instancetype)fromNib {
    return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil] objectAtIndex:0];
}
@end

InputCollectionViewCell实现

#import "InputCollectionViewCell.h"
#define IDENTIFFIER @"InputCollectionViewCell"

@implementation InputCollectionViewCell

-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
      if (self) {
          [self loadFromNib];
  
      }
      return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
       if (self) {
           [self loadFromNib];
           self.userInteractionEnabled = YES;
           
           // Initialize what is needed
       }
       return self;
}

+ (NSString *) identifier {
    return IDENTIFFIER;
}


- (void)loadFromNib {
    UIView *nibView = [[self class] fromNib];
    if (nibView) {
        nibView.frame = self.bounds;
        nibView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self addSubview:nibView];
        nibView.backgroundColor = [UIColor redColor];
    }
}

@end

MainViewController关键代码

#import "MainViewController.h"

@interface MainViewController ()

@end

@implementation MainViewController
@synthesize menuCollectionView;

- (void)viewDidLoad {
    [super viewDidLoad];
 
    [self.menuCollectionView registerClass:[InputCollectionViewCell class] forCellWithReuseIdentifier:[InputCollectionViewCell identifier]];

    menuCollectionView.delegate = self;
    menuCollectionView.dataSource = self;
}
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [InputCollectionViewCell dealloc];
}


- (nonnull __kindof UICollectionViewCell *)collectionView:(nonnull UICollectionView *)collectionView cellForItemAtIndexPath:(nonnull NSIndexPath *)indexPath {
    // Dequeue a reusable cell from the collection view.
    InputCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:[InputCollectionViewCell identifier] forIndexPath:indexPath];
     [cell addBorderAndShadow];

       // Configure the cell with data for the index path.
 //      MyData *data = self.myDataArray[indexPath.item];
    //   [cell configureWithData:data];

       // Return the configured cell.
       return cell;
}
@end

Xib配置截图:
Xib配置截图


修复步骤

1. 检查并修复Outlet关联

  • 打开对应的Xib文件,找到名为brickWall的控件,右键点击查看连线列表,确认所有连线都指向InputCollectionViewCell类,且该类的.h文件中存在对应的属性声明:
    @property (nonatomic, weak) IBOutlet <控件类型,如UIView/UIImageView> *brickWall;
    
  • 如果之前删除过该属性但未清除Xib中的连线,直接删除无效的连线即可。

2. 修正Nib加载的Owner参数

当前UIView (NIBLoader)中fromNib方法的owner传的是类对象(self),这会导致KVC关联错误。修改为:

@implementation UIView (NIBLoader)
+ (instancetype)fromNib {
    // 加载Nib时owner设为nil,避免不必要的KVC关联
    return [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:nil] firstObject];
}
@end

或者在InputCollectionViewCell的loadFromNib方法中直接指定owner为当前实例:

- (void)loadFromNib {
    UIView *nibView = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil].firstObject;
    if (nibView) {
        nibView.frame = self.bounds;
        nibView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [self addSubview:nibView];
        nibView.backgroundColor = [UIColor redColor];
    }
}

3. 修正CollectionView的Cell注册方式

使用Xib创建的Cell,应该注册Nib而非Class,否则CollectionView会用纯代码创建Cell,导致Xib加载逻辑冲突。修改MainViewController的viewDidLoad:

- (void)viewDidLoad {
    [super viewDidLoad];
 
    // 替换registerClass为registerNib
    UINib *cellNib = [UINib nibWithNibName:[InputCollectionViewCell identifier] bundle:nil];
    [self.menuCollectionView registerNib:cellNib forCellWithReuseIdentifier:[InputCollectionViewCell identifier]];

    menuCollectionView.delegate = self;
    menuCollectionView.dataSource = self;
}

同时,移除InputCollectionViewCell中initWithFrame:和initWithCoder:里的[self loadFromNib]调用,因为注册Nib后CollectionView会自动加载Xib创建Cell,重复加载会导致子视图重复添加及KVC错误。

4. 删除手动调用dealloc的代码

viewWillDisappear中的[InputCollectionViewCell dealloc];是错误操作,dealloc由系统自动调用,手动调用会引发内存问题,直接删除该行代码。


内容的提问来源于stack exchange,提问作者Jael Ruvalcaba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 22:05:28