Skip to content

SwiftUI KVO Crash #1589

@LuckyCat7848

Description

@LuckyCat7848

必现/偶发?
必现

怎么样重现这个bug

  1. 把 MJRefreshFooter 使用 UIViewRepresentable 包装成 SwiftUI 中可以使用的 View;
  2. 在 SwiftUI 页面使用加载,页面返回销毁。此时崩溃在 MJRefreshComponent line 105 removeObservers() 方法中。
    崩溃日志:
    *** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <MJRefreshBackNormalFooter 0x126b7e7b0> for the key path "contentOffset" from <TtGC7SwiftUI16PlatformViewHostGVS_P10$1c8b6b12832PlatformViewRepresentableAdaptorV9JKSwiftUI26SwiftUIMJRefreshFooterView_ 0x126b7f3d0> because it is not registered as an observer.'

分析原因:

  1. 在这里 self.superview 移除KVO监听时,移除的是 contentOffset 和 contentSize,而SwiftUI场景走到这里的 self.superView 不是UIScrollView的子类,没有添加这两个属性及监听,因此崩溃。
  • (void)removeObservers
    {
    [self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentOffset];
    [self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentSize];
    [self.pan removeObserver:self forKeyPath:MJRefreshKeyPathPanState];
    self.pan = nil;
    }

解决建议:

  1. 这里移除KVO的时候判断一下:
    if (self.superview && ![self.superview isKindOfClass:[UIScrollView class]]) return;

运行环境

  • iPhone12
  • iOS15.4
  • Xcode14.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions