This application is modifying the autolayout engine from a background thread

error : This application is modifying the autolayout engine from a background thread

此问题是由于在子的线程中更新了 UI 所导致的,
解决方法:找到在子线程中更新ui的代码,将他们在主线程更新即可;

但 Xcode 提示错误信息不太明确,在调用堆栈根本无法发现错误是由哪句代码导致的,当然要调试这个问题可以使用PSPDFUIKitMainThreadGuard.m 定位错误的代码,这个是 PSPDFKit 框架中用到的专门查找代码中哪些代码会在辅线程中更新 UI 的工具,PSPDFUIKitMainThreadGuard是通过在拦截所有 UIKit 中对 setNeedsDisplay 和 setNeedsLayout 的调用,判断当前线程如果是子线程则抛出异常

使用时将PSPDFUIKitMainThreadGuard手动拖入项目,并将其编译选项设置为 -fno-objc-arc
运行后,当有任何类似的错误发生时,Xcode 会在错误发生的代码停下

部分代码:

 for (NSString *selStr in @[PROPERTY(setNeedsLayout), PROPERTY(setNeedsDisplay), PROPERTY(setNeedsDisplayInRect:)]) {
            SEL selector = NSSelectorFromString(selStr);
            SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"pspdf_%@", selStr]);
            if ([selStr hasSuffix:@":"]) {
                PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(__unsafe_unretained UIView *_self, CGRect r) {
                    // Check for window, since *some* UIKit methods are indeed thread safe.
                    // https://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iPhoneOS4.html
                    /*
                     Drawing to a graphics context in UIKit is now thread-safe. Specifically:

                     The routines used to access and manipulate the graphics context can now correctly handle contexts residing on different threads.

                     String and image drawing is now thread-safe.

                     Using color and font objects in multiple threads is now safe to do.
                     */
                    if (_self.window) PSPDFAssertIfNotMainThread();
                    ((void ( *)(id, SEL, CGRect))objc_msgSend)(_self, newSelector, r);
                });
            }else {
                PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(__unsafe_unretained UIView *_self) {
                    if (_self.window) {
                        if (!NSThread.isMainThread) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
                            dispatch_queue_t queue = dispatch_get_current_queue();
#pragma clang diagnostic pop
                            // iOS 8 layouts the MFMailComposeController in a background thread on an UIKit queue.
                            // https://github.com/PSPDFKit/PSPDFKit/issues/1423
                            if (!queue || !strstr(dispatch_queue_get_label(queue), "UIKit")) {
                                PSPDFAssertIfNotMainThread();
                            }
                        }
                    }
                    ((void ( *)(id, SEL))objc_msgSend)(_self, newSelector);
                });
            }
        }
    }
}

Demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容