class 类型实例的更改未反映在其他参考中

Change in an instance of class type is not reflected in other reference

上下文

我正在使用 NSCollectionLayoutDecorationItem 和 NSCollectionLayoutSection 构建 UICollectionViewLayout。

我做的步骤是:

  1. 实例化一个NSCollectionLayoutSection,命名为section
  2. 实例化一个NSCollectionLayoutDecorationItem,命名为decoration
  3. 为数组分配装饰section.decorationItems
  4. 通过填充其 contentInsets 来更新装饰

但是,我在第 4 步中所做的更新并未反映在 section.decorationItems 中。 (交换第 3 步和第 4 步可以解决问题,但仍然不能解释问题。)

问题

NSCollectionLayoutDecorationItem is a class, hence reference type. 为什么更改没有反映在数组 section.decorationItems 中?我不熟悉 objective-c,NSCollectionLayoutDecorationItem 是不是类似于 objc 中的不可变 class?

代码片段

let section = NSCollectionLayoutSection(group: group) // Step 1
let decoration = NSCollectionLayoutDecorationItem.background(elementKind: Self.sectionBackgroundDecorationElementKind) // Step 2
section.decorationItems = [decoration] // Step 3
print("before change \(section.decorationItems)")
decoration.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5) // Step 4 --> change not reflected in section.decorationItems
print("after change \(section.decorationItems)") // same output as "before change"

在您分配给 section.decorationItems 的那一刻,您传入的实例就会生成一个副本。因此 section.decorationItems[0] 是您的 decoration 的副本,但也是一个完全不同的副本实例。这就是为什么您对一个所做的更改不会影响另一个。您可以在调试器中看到这一点,因为内存地址不同。

如果你想在分配给 section.decorationItems 后更改值,你必须像 section.decorationItems[0].contentInsets = ... 那样做,或者可能用更新的实例重新分配给 section.decorationItems,所以它可以制作新副本。

UIKit 中有许多地方在您分配 class 的某个实例以提供某些配置时创建副本。即使它是引用类型。通常文档会提到它,但 NSCollectionLayoutSection.

不会