切换夜间模式的问题, myCacheAttr 可能会存在空, 导致视图背景被清空
issumao opened this issue · 5 comments
- 切换夜间模式
- JJCollectionReusableView 触发 traitCollectionDidChange 时, _myCacheAttr 可能会存在空, 导致视图背景被清空
- 观察到的可能原因是, JJCollectionViewRoundFlowLayout 的 prepareLayout 过多的被重复调用, decorationViewAttrs 存储的值被释放, 导致 JJCollectionReusableView 的弱引用 myCacheAttr 也被释放. 在切换夜间模式时, 造成上诉情况.
- 可能的修复途径, 为JJCollectionViewRoundLayoutAttributes 覆写 isEqual 方法
还请复查, 并评估最优解
- 切换夜间模式
- JJCollectionReusableView 触发 traitCollectionDidChange 时, _myCacheAttr 可能会存在空, 导致视图背景被清空
- 观察到的可能原因是, JJCollectionViewRoundFlowLayout 的 prepareLayout 过多的被重复调用, decorationViewAttrs 存储的值被释放, 导致 JJCollectionReusableView 的弱引用 myCacheAttr 也被释放. 在切换夜间模式时, 造成上诉情况.
- 可能的修复途径, 为JJCollectionViewRoundLayoutAttributes 覆写 isEqual 方法
还请复查, 并评估最优解
感谢回复,我这边排查一下。
- 切换夜间模式
- JJCollectionReusableView 触发 traitCollectionDidChange 时, _myCacheAttr 可能会存在空, 导致视图背景被清空
- 观察到的可能原因是, JJCollectionViewRoundFlowLayout 的 prepareLayout 过多的被重复调用, decorationViewAttrs 存储的值被释放, 导致 JJCollectionReusableView 的弱引用 myCacheAttr 也被释放. 在切换夜间模式时, 造成上诉情况.
- 可能的修复途径, 为JJCollectionViewRoundLayoutAttributes 覆写 isEqual 方法
还请复查, 并评估最优解
您好,我在对demo进行排查,暂时没发现对应描述的问题。
我这边使用了模拟器、iPhone 15.3版本。通过进行不停的切换白天模式、夜间模式。都没出现对应问题。
您这边是否可以提供一下您出问题的情况更多描述或者demo呢?
你好, 我尝试在Demo上实现了上述现象, 采用github上直接下载的demo, 模拟器 iPhone 13, 版本 15.0, Xcode - Version 13.1.
大致模拟一下我app的一个流程. 对Demo做了以下3处修改:
- 在 ViewDidLoad 的尾部增加一个延时1秒的reload
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self.myCollectionView reloadData];
});
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 3;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 4;
}
- didSelectItemAtIndexPath的方法里, 增加切换夜间模式的来回切换
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
[[UIApplication sharedApplication].windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (@available(iOS 13.0, *)) {
obj.overrideUserInterfaceStyle = (obj.overrideUserInterfaceStyle == UIUserInterfaceStyleLight) ? UIUserInterfaceStyleDark : UIUserInterfaceStyleLight;
};
}];
}
点击 item 来回切换夜间模式, 第一个item的背景色会丢失
你好, 我尝试在Demo上实现了上述现象, 采用github上直接下载的demo, 模拟器 iPhone 13, 版本 15.0, Xcode - Version 13.1. 大致模拟一下我app的一个流程. 对Demo做了以下3处修改:
- 在 ViewDidLoad 的尾部增加一个延时1秒的reload
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self.myCollectionView reloadData]; });
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{ return 3; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ return 4; }
- didSelectItemAtIndexPath的方法里, 增加切换夜间模式的来回切换
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ [[UIApplication sharedApplication].windows enumerateObjectsUsingBlock:^(__kindof UIWindow * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { if (@available(iOS 13.0, *)) { obj.overrideUserInterfaceStyle = (obj.overrideUserInterfaceStyle == UIUserInterfaceStyleLight) ? UIUserInterfaceStyleDark : UIUserInterfaceStyleLight; }; }]; }
点击 item 来回切换夜间模式, 第一个item的背景色会丢失
感谢您的反馈,我这边按照您的方案进行尝试。
- 切换夜间模式
- JJCollectionReusableView 触发 traitCollectionDidChange 时, _myCacheAttr 可能会存在空, 导致视图背景被清空
- 观察到的可能原因是, JJCollectionViewRoundFlowLayout 的 prepareLayout 过多的被重复调用, decorationViewAttrs 存储的值被释放, 导致 JJCollectionReusableView 的弱引用 myCacheAttr 也被释放. 在切换夜间模式时, 造成上诉情况.
- 可能的修复途径, 为JJCollectionViewRoundLayoutAttributes 覆写 isEqual 方法
还请复查, 并评估最优解
您好,经过各种排查和复现,在排查中感觉应该特定数据量才会出现该问题。
现在初步判断为,collectionview系统在setlayout的情况下,会对UICollectionViewLayoutAttributes进行不同程度的copy,导致前期保存下来的_myCacheAttr存在为空的情况。
现在解决方案如下:在JJCollectionViewRoundLayoutAttributes下实现NSCopying,重写JJCollectionViewRoundLayoutAttributes 的copy方法,捕获系统copy,验证后续_myCacheAttr正常。