在iOS 10上崩溃的问题:viewDidMoveToWindow:shouldAppearOrDisappear:

4

最近我的应用在生产环境中崩溃了,但是无法在调试模式下重现此错误。

Crashlytics 报告的错误信息如下:

UIKit
-[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:]

SIGABRT ABORT 0x00000001825d4d74

    Crashed: com.apple.main-thread
    0  libsystem_kernel.dylib         0x1825d4d74 __abort_with_payload + 8
    1  libsystem_kernel.dylib         0x1825d1480 abort_with_payload_wrapper_internal + 100
    2  libsystem_kernel.dylib         0x1825d141c abort_with_payload_wrapper_internal + 34
    3  libobjc.A.dylib                0x18203fed8 _objc_fatalv(unsigned long long, unsigned long long, char const*, char*) + 112
    4  libobjc.A.dylib                0x18203fe30 __objc_error + 42
    5  libobjc.A.dylib                0x182052cd4 weak_entry_insert(weak_table_t*, weak_entry_t*) + 318
    6  libobjc.A.dylib                0x182058664 objc_initWeak + 324
    7  UIKit                          0x1894ce1bc -[UIViewController viewDidMoveToWindow:shouldAppearOrDisappear:] + 2068
    8  UIKit                          0x18944db5c -[UIView(Internal) _didMoveFromWindow:toWindow:] + 1352
    9  UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    10 UIKit                          0x189471714 -[UIScrollView _didMoveFromWindow:toWindow:] + 92
    11 UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    12 UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    13 UIKit                          0x189471714 -[UIScrollView _didMoveFromWindow:toWindow:] + 92
    14 UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    15 UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    16 UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    17 UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    18 UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    19 UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    20 UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    21 UIKit                          0x18944d8e4 -[UIView(Internal) _didMoveFromWindow:toWindow:] + 720
    22 UIKit                          0x18944cd90 __45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 156
    23 Foundation                     0x184034510 -[NSISEngine withBehaviors:performModifications:] + 168
    24 UIKit                          0x18944cc04 -[UIView(Hierarchy) _postMovedFromSuperview:] + 820
    25 UIKit                          0x18974a078 __UIViewWasRemovedFromSuperview + 172
    26 UIKit                          0x18944bc80 -[UIView(Hierarchy) removeFromSuperview] + 512
    27 UIKit                          0x1897a23dc __71-[UIPresentationController _initViewHierarchyForPresentationSuperview:]_block_invoke.629 + 1044
    28 UIKit                          0x18979c4fc -[UIPresentationController transitionDidFinish:] + 124
    29 UIKit                          0x18990afc8 -[_UICurrentContextPresentationController transitionDidFinish:] + 40
    30 UIKit                          0x1897a012c __56-[UIPresentationController runTransitionForCurrentState]_block_invoke_2 + 188
    31 UIKit                          0x189578ad4 -[_UIViewControllerTransitionContext completeTransition:] + 116
    32 UIKit                          0x1895788c0 -[UITransitionView notifyDidCompleteTransition:] + 252
    33 UIKit                          0x1895783dc -[UITransitionView _didCompleteTransition:] + 1240
    34 UIKit                          0x189577ef0 -[UITransitionView _transitionDidStop:finished:] + 124
    35 UIKit                          0x189489b48 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 312
    36 UIKit                          0x189489988 -[UIViewAnimationState animationDidStop:finished:] + 160
    37 QuartzCore                     0x186912404 CA::Layer::run_animation_callbacks(void*) + 260
    38 libdispatch.dylib              0x1824911c0 _dispatch_client_callout + 16
    39 libdispatch.dylib              0x182495d6c _dispatch_main_queue_callback_4CF + 1000
    40 CoreFoundation                 0x1835b5f2c __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
    41 CoreFoundation                 0x1835b3b18 __CFRunLoopRun + 1660
    42 CoreFoundation                 0x1834e2048 CFRunLoopRunSpecific + 444
    43 GraphicsServices               0x184f65198 GSEventRunModal + 180
    44 UIKit                          0x1894bc628 -[UIApplication _run] + 684
    45 UIKit                          0x1894b7360 UIApplicationMain + 208
    46 <App Name>                     0x100081590 main (main.m:14)
    47 libdispatch.dylib              0x1824c45b8 (Missing)

大多数日志显示用户的RAM内存空闲率在1%至3%之间,但有些超过了10%。
此外,我的应用程序使用Sentry跟踪错误,但这个错误不在Sentry中,只在Fabric中出现。
我的大多数用户使用iOS 10,但仍然有一些使用iOS 9,这个崩溃似乎不影响这些用户。所以它似乎与iOS 10有关。
我已经在这里搜索过了,但是我没有找到解决方案,甚至线索。有人可以帮我找到线索吗?
编辑:
关于评论所提到的与UIViewController相关的新代码是:
    - (IBAction)tapClose:(id)sender {
        [self close];
    }

    - (void)close {
        _dismissing = YES;

        CGFloat height = self.view.superview.frame.size.height;
        [UIView animateWithDuration:0.2 animations:^{
            [self.view setFrame:CGRectMake(0, height, self.view.frame.size.width, self.view.frame.size.height)];
            _overlay.alpha = 0;
        }                completion:^(BOOL finished) {
            if (finished) {
                [self.view removeFromSuperview];
                [_overlay removeFromSuperview];
                if (self.blockWhenClose) {
                    self.blockWhenClose();
                }
            }
        }];
    }

    - (void)showIn:(UIViewController *)viewcontroller {
        CGRect frame = viewcontroller.view.frame;
        CGFloat height = [self calculateHeight:frame.size.height / 2];
        [self.view setFrame:CGRectMake(0, frame.size.height, frame.size.width, height)];
        [_overlay setFrame:frame];
        _overlay.alpha = 0;
        [viewcontroller addChildViewController:self];
        [viewcontroller.view addSubview:_overlay];
        [viewcontroller.view addSubview:self.view];
        [self didMoveToParentViewController:viewcontroller];
        [UIView animateWithDuration:_duration animations:^{
            _overlay.alpha = 1;
            [self.view setFrame:CGRectMake(0, frame.size.height - height, frame.size.width, height)];
        }];
        _show = YES;
    }

但是我不知道崩溃发生的确切位置。

_UIViewControllerTransitionContext意味着在切换UIViewController之间发生。您是否正在使用类似于“侧边菜单”控制器或执行自定义的UIViewControllerAnimation - KrishnaCA
视图层次结构在转换时看起来损坏了。你能分享相关的代码吗? - ystack
@KrishnaCA,没有侧边菜单,并且我没有引入任何UIViewControllerAnimation。有很大的变化,但是与UIViewController更改相关的唯一新代码是(只是在问题中添加)。 - Alberto Cantallops
我们面临着相同的崩溃情况,你能找到解决方案吗? - Jordi Puigdellívol
@JordiPuigdellívol 我已经缩小了问题的范围,但它仍然存在。在我的情况下,这与弱引用有关无法形成对类<class name>实例(0x1093ae3c0)的弱引用。可能是该对象被过度释放或正在进行解除分配的过程。因为视图控制器位于分页视图中。我可以通过快速切换页面来重现它。在我的情况下,当创建自定义视图时,问题发生在tableView:viewForHeaderInSection:。希望这能帮到你。 - Alberto Cantallops
@AlbertoCantallops 是的,我相信在我的情况下也会发生分页视图控制器的问题,但是我自己还无法复现它...只有我的客户在非常高强度的使用中遇到了这个问题:( - Jordi Puigdellívol
1个回答

0

对我来说,这始于iOS 14。

问题是,我的代码中将控制器(A)的视图作为子视图添加到另一个控制器(B)中,但没有保留对控制器(A)本身的引用。控制器(A)被释放后,下一次视图即将出现或消失时,它会尝试通知控制器(A),从而导致崩溃。

解决方案:

  • 手动保留对控制器的引用
  • 或使用addChildViewController自动完成上述操作

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接