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

Xcode 16 Beta自定义UICollectionViewCell出队错误排查求助

Xcode 16 Beta开发iOS应用时UICollectionView运行时异常排查与解决

问题现象

运行iOS应用时触发NSInternalInconsistencyException异常,错误核心提示如下:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Expected dequeued view to be returned to the collection view in preparation for display. When the collection view's data source is asked to provide a view for a given index path, ensure that a single view is dequeued and returned to the collection view. Avoid dequeuing views without a request from the collection view. For retrieving an existing view in the collection view, use -[UICollectionView cellForItemAtIndexPath:] or -[UICollectionView supplementaryViewForElementKind:atIndexPath:]. 

异常在@UIApplicationMain标记的入口处抛出,关联自定义单元格<MyProject.MyCollectionViewCell>。

完整堆栈跟踪:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Expected dequeued view to be returned to the collection view in preparation for display. When the collection view's data source is asked to provide a view for a given index path, ensure that a single view is dequeued and returned to the collection view. Avoid dequeuing views without a request from the collection view. For retrieving an existing view in the collection view, use -[UICollectionView cellForItemAtIndexPath:] or -[UICollectionView supplementaryViewForElementKind:atIndexPath:]. Dequeued view: <MyProject.MyCollectionViewCell: 0x15393d780; baseClass = UICollectionViewCell; frame = (34 35; 325 90); opaque = NO; backgroundColor = UIExtendedGrayColorSpace 0 0; layer = <CALayer: 0x6000045af9a0>>;; Collection view: <UICollectionView: 0x11ddf1e00; frame = (0 0; 393 582.333); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x600000de1920>; backgroundColor = <UIDynamicCatalogColor: 0x60000219acb0; name = sptBackground>; layer = <CALayer: 0x6000007510a0>; contentOffset: {0, 0}; contentSize: {393, 159}; adjustedContentInset: {0, 0, 0, 0}; layout: <UICollectionViewFlowLayout: 0x1042a4c70>; dataSource: <MyProject.MyCollectionsViewController: 0x11dde5200>>'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001804b70ec __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x000000018008ede8 objc_exception_throw + 72
    2   Foundation                          0x0000000180e73aa8 _userInfoForFileAndLine + 0
    3   UIKitCore                           0x00000001851ace44 __43-[UICollectionView _updateVisibleCellsNow:]_block_invoke.444 + 136
    4   UIKitCore                           0x0000000185a9811c -[_UICollectionViewSubviewManager removeAllDequeuedViewsWithEnumerator:] + 188
    5   UIKitCore                           0x00000001851ac90c -[UICollectionView _updateVisibleCellsNow:] + 4000
    6   UIKitCore                           0x00000001851b1714 -[UICollectionView layoutSubviews] + 284
    7   UIKitCore                           0x0000000186016438 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2404
    8   QuartzCore                          0x000000018b059eb0 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 432
    9   UIKitCore                           0x000000018600583c -[UIView(Hierarchy) layoutBelowIfNeeded] + 308
    10  UIKitCore                           0x000000018529304c -[UINavigationController _layoutViewController:] + 812
    11  UIKitCore                           0x000000018528cac4 -[UINavigationController _layoutTopViewControllerLookForNested:] + 416
    12  UIKitCore                           0x000000018528b004 -[UINavigationController _didEndTransitionFromView:toView:wasCustom:] + 820
    13  UIKitCore                           0x0000000185c31908 -[_UIViewControllerTransitionConductor _startTransition:fromViewController:toViewController:] + 1004
    14  UIKitCore                           0x0000000185c311b0 -[_UIViewControllerTransitionConductor startDeferredTransitionIfNeeded] + 640
    15  UIKitCore                           0x0000000185293d4c -[UINavigationController __viewWillLayoutSubviews] + 80
    16  UIKitCore                           0x000000018527bb00 -[UILayoutContainerView layoutSubviews] + 168
    17  UIKitCore                           0x0000000186016438 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 2404
    18  QuartzCore                          0x000000018b059eb0 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 432
    19  QuartzCore                          0x000000018b064c34 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 124
    20  QuartzCore                          0x000000018af99c58 _ZN2CA7Context18commit_transactionEPNS_11TransactionEdPd + 464
    21  QuartzCore                          0x000000018afc8468 _ZN2CA11Transaction6commitEv + 652
    22  UIKitCore                           0x0000000185ab8260 __34-[UIApplication _firstCommitBlock]_block_invoke_2 + 32
    23  CoreFoundation                      0x000000018041b0ec __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 20
    24  CoreFoundation                      0x000000018041a824 __CFRunLoopDoBlocks + 352
    25  CoreFoundation                      0x00000001804150c8 __CFRunLoopRun + 812
    26  CoreFoundation                      0x0000000180414960 CFRunLoopRunSpecific + 536
    27  GraphicsServices                    0x000000019016fb10 GSEventRunModal + 160
    28  UIKitCore                           0x0000000185a9f650 -[UIApplication _run] + 796
    29  UIKitCore                           0x0000000185aa3848 UIApplicationMain + 124
    30  MyProject.debug.dylib          0x000000010983da34 __debug_main_executable_dylib_entry_point + 64
    31  dyld                                0x000000010298d410 start_sim + 20
    32  ???                                 0x0000000102b92154 0x0 + 4340654420
    33  ???                                 0x352f000000000000 0x0 + 3832281807915581440
)
libc++abi: terminating due to uncaught exception of type NSException

问题定位

异常根源在cellForItemAt方法的以下代码块:

let cell = collectionView.dequeueReusableCell(withReuseIdentifier:item.reuseIdentifier(), for: indexPath) as UICollectionViewCell

 switch cell {
 case is CollectionViewCell:

if let customCell = cell as? CustomCollectionViewCell {
    
    if Device.isPhone && (item is FirstTypeItem || item is SecondTypeItem) {
        
        guard let phoneCell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhoneCell", for: indexPath) as? PhoneCollectionCell else {
            return cell // Return the original cell if casting fails
        }
        
        phoneCell.setSomeValue(value)
        return phoneCell
    }
    
    customCell.setSomeValue(otherValue)
    return customCell
}

return cell

存在两个关键问题:

  1. 同一indexPath重复出队单元格:先调用一次dequeueReusableCell获取cell,满足条件时又调用一次获取phoneCell,首次出队的cell未返回给集合视图,违反UICollectionView的复用机制,触发异常。
  2. 复用标识符拼写不一致:注册PhoneCell时用的是"PHoneCell",但出队时用的是"PhoneCell",导致单元格加载失败,IBOutlet绑定为nil。

解决方案

1. 修正单元格出队逻辑

每个indexPath仅允许一次dequeueReusableCell调用,直接根据数据类型和设备类型选择对应的复用标识符,修改后的代码示例:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let item = dataSource[indexPath.item]
    
    // 直接根据条件选择要出队的单元格
    if Device.isPhone && (item is FirstTypeItem || item is SecondTypeItem) {
        let phoneCell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhoneCell", for: indexPath) as! PhoneCollectionCell
        phoneCell.setSomeValue(value)
        return phoneCell
    } else {
        let customCell = collectionView.dequeueReusableCell(withReuseIdentifier: item.reuseIdentifier(), for: indexPath) as! CustomCollectionViewCell
        customCell.setSomeValue(otherValue)
        return customCell
    }
}

2. 修正复用标识符拼写错误

确保注册和使用的标识符完全一致:

// 注册PhoneCell时使用正确的标识符
collectionView.register(PhoneCollectionCell.self, forCellWithReuseIdentifier: "PhoneCell")

3. 额外检查(可选)

  • 若使用xib创建PhoneCollectionCell,需用xib方式注册:
    collectionView.register(UINib(nibName: "PhoneCollectionCell", bundle: nil), forCellWithReuseIdentifier: "PhoneCell")
    
  • 检查PhoneCollectionCell的IBOutlet连接是否正确,避免因视图未加载导致的nil问题。

内容的提问来源于stack exchange,提问作者Martin Van Nostrand

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 03:05:56