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

RxSwift代码创建UITableView时dequeueReusableCell崩溃问题求助

问题

我尝试通过代码在ViewController中添加UITableView,注册Cell后,在Driver绑定流程中调用dequeueReusableCell时发生崩溃。

崩溃发生在该行:let cell = tableView.dequeueReusableCell(withIdentifier: "ImageWithLabelsTableViewCell") as! ImageWithLabelsTableViewCell
错误信息:-[UIImageView _isSymbolImage]: unrecognized selector sent to instance 0x11389c4d0
同时收到警告:[TableView] Warning once only: UITableView was told to layout its visible cells and other contents without being in the view hierarchy...

ViewController代码

extension NewProfileViewController {
enum CellType {
    case header(viewModel: ImageWithLabelType)
    case accountBalanceCell
    case marketOpenCell
    case transactionCounterCell
    case extraActionsCell
}
}

class NewProfileViewController: BaseViewController {

let tableView = UITableView()

let disposeBag = DisposeBag()

var viewModel: TableViewWithHeaderImageType
private var headerState: HeaderState = .white

init(viewModel: TableViewWithHeaderImageType) {
    self.viewModel = viewModel
    navigator = viewModel.navigator
    super.init(nibName: nil, bundle: nil)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
    super.viewDidLoad()
    navigator = viewModel.navigator
    
    configureTableView()

    self.view.addSubview(tableView)

    tableView.backgroundColor = ColorName.white
    tableView.separatorStyle = .none
    tableView.translatesAutoresizingMaskIntoConstraints = false
    
    tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
 
    bind()

}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    

    configureNavBar()
}

func configureNavBar() {
    let investImage = UIImage(named: "pepperInvestWhite")
    let imageView = UIImageView(image: investImage)
    addCustomTitleView(view: imageView)
    addLeftNavigationItem(menuItem: .whiteChat)
}

override func leftNavigationItemClicked(navigationItem: NavigationItem) {
   // openPepperChat()
}


private func bind() {
    viewModel.items.drive(tableView.rx.items) { tableView, index, element in
        switch element {
        case .header:
            let cell = tableView.dequeueReusableCell(withIdentifier: "ImageWithLabelsTableViewCell") as! ImageWithLabelsTableViewCell
           // cell.selectionStyle = .none
            return cell
        case .accountBalanceCell:
            let cell = tableView.dequeueReusableCell(withIdentifier: "sideMenuMyBalanceCell") as! ProfileBaseCell
            cell.selectionStyle = .none
            cell.confgiureCell()
            //cell.delegate = self
            cell.layer.masksToBounds = true
            return cell
        case .marketOpenCell:
            let cell = tableView.dequeueReusableCell(withIdentifier: "marketTimeOpenCell") as! ProfileBaseCell
            cell.selectionStyle = .none
            cell.confgiureCell()
            //cell.delegate = self
            cell.layer.masksToBounds = true
            return cell
        case .transactionCounterCell:
            let cell = tableView.dequeueReusableCell(withIdentifier: "transactionCounterCell") as! ProfileBaseCell
            cell.selectionStyle = .none
            cell.confgiureCell()
            //cell.delegate = self
            cell.layer.masksToBounds = true
            return cell
        case .extraActionsCell:
            let cell = tableView.dequeueReusableCell(withIdentifier: "extraActionsCell") as! ProfileBaseCell
            cell.selectionStyle = .none
            cell.confgiureCell()
            //cell.delegate = self
            cell.layer.masksToBounds = true
            return cell
        }
    }.disposed(by: disposeBag)
    
    viewModel.fetchData()

}

private func configureTableView() {
    tableView.register(UINib(nibName: "ImageWithLabelsTableViewCell", bundle: nil), forCellReuseIdentifier: "ImageWithLabelsTableViewCell")
    tableView.register(UINib(nibName: "sideMenuMyBalanceCell", bundle: nil), forCellReuseIdentifier: "sideMenuMyBalanceCell")
    tableView.register(UINib(nibName: "marketTimeOpenCell", bundle: nil), forCellReuseIdentifier: "marketTimeOpenCell")
    tableView.register(UINib(nibName: "CryptoMarketTimeOpenTableViewCell", bundle: nil), forCellReuseIdentifier: "CryptoMarketTimeOpenTableViewCell")
    tableView.register(UINib(nibName: "transactionCounterCell", bundle: nil), forCellReuseIdentifier: "transactionCounterCell")
    tableView.register(UINib(nibName: "extraActionsCell", bundle: nil), forCellReuseIdentifier: "extraActionsCell")
    
    tableView.backgroundColor = ColorName.white
    tableView.separatorStyle = .none
}
}

ViewModel代码

final class NewProfileViewModel: TableViewWithHeaderImageType {
var didPushRightNavigationItem = PublishRelay<Void>()

let moneyTransferStatus = BehaviorRelay<MoneyTransferStatus>(value: .noMoney)
private var profileEventFactory: ProfileEventFactory
var navigator: ProfileNavigtor
lazy var items = _items.asDriver(onErrorJustReturn: [])
private let _items = BehaviorRelay<[NewProfileViewController.CellType]>(value: [])

private var headerViewModel: ImageWithLabelType!

init(navigator: ProfileNavigtor, profileEventFactory: ProfileEventFactory) {
    self.navigator = navigator
    self.profileEventFactory = profileEventFactory
    subscribe()
}

private func subscribe() {
    
    let titleAttributedString = NSMutableAttributedString(string: L10n.funYouCameBack, attributes: [NSAttributedString.Key.font: UIFont(name: "Orion-ExtraBold", size: 36)!,NSAttributedString.Key.foregroundColor: ColorName.black])
    
    let name = User.me?.firstNameHE == "" ? User.me?.name : User.me?.firstNameHE ?? "שם"
    let nameAttributedString = NSMutableAttributedString(string: name ?? "", attributes: [NSAttributedString.Key.font: UIFont(name: "Orion-ExtraBold", size: 36)!,NSAttributedString.Key.foregroundColor: ColorName.white])
    
    
    headerViewModel = ImageWithLabelViewModelCell(imageName: "profileHeader", headerTitle: titleAttributedString, headerName: nameAttributedString)
}

func fetchData() {
    var cellsData = [NewProfileViewController.CellType]()
    cellsData.append(.header(viewModel: headerViewModel))
    cellsData.append(.accountBalanceCell)
    cellsData.append(.marketOpenCell)
    cellsData.append(.transactionCounterCell)
    cellsData.append(.extraActionsCell)

    _items.accept(cellsData)
}
}
解决方案

1. 调整TableView的视图层级加入时机

警告信息明确指出UITableView在未加入视图层级时就被要求布局内容,这会触发异常布局逻辑。需要先将TableView添加到视图层级,再执行配置和绑定操作:

修改viewDidLoad方法的顺序:

override func viewDidLoad() {
    super.viewDidLoad()
    navigator = viewModel.navigator
    
    // 先添加到视图
    self.view.addSubview(tableView)
    // 设置约束
    tableView.backgroundColor = ColorName.white
    tableView.separatorStyle = .none
    tableView.translatesAutoresizingMaskIntoConstraints = false
    
    tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    
    // 再配置TableView
    configureTableView()
    // 最后绑定数据
    bind()
}

2. 检查ImageWithLabelsTableViewCell的XIB文件

崩溃信息显示向UIImageView发送了它不识别的_isSymbolImage方法,大概率是XIB文件存在问题:

  • 确认XIB中根视图是UITableViewCell,而非UIImageView或其他控件
  • 检查Cell的class是否正确设置为ImageWithLabelsTableViewCell
  • 验证XIB中所有IBOutlet连接是否正确,没有关联到错误的控件

3. 安全解包Cell(可选但推荐)

强制解包as!会在Cell获取失败时直接崩溃,建议改为可选绑定,增加代码健壮性:

case .header:
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "ImageWithLabelsTableViewCell") as? ImageWithLabelsTableViewCell else {
        fatalError("无法获取ImageWithLabelsTableViewCell") // 或返回自定义占位Cell
    }
    return cell

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 01:30:47