更新到 Xcode 10.2 后出现 PDFKit 问题。有什么办法解决吗?
There's problem with PDFKit appeared after update to Xcode 10.2. Is there any way to solve?
当我尝试使用 pdfkit 显示 pdf 文件时,应用程序崩溃了。这是简单的例子 :
import UIKit
import PDFKit
class ViewController: UIViewController {
@IBOutlet weak var pdfView: PDFView!
override func viewDidLoad() {
super.viewDidLoad()
if let path = Bundle.main.path(forResource: "file", ofType: "pdf") {
let url = URL(fileURLWithPath: path)
if let pdfDocument = PDFDocument(url: url) {
pdfView.displayMode = .singlePageContinuous
pdfView.autoScales = true
// pdfView.displayDirection = .horizontal
pdfView.document = pdfDocument
}
}
}
}
这与 "uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan nan]'" 一起崩溃:
2019-03-26 21:09:47.837837+0400 pdfKitTest[3163:93151] libMobileGestalt MobileGestalt.c:890: MGIsDeviceOneOfType is not supported on this platform.
2019-03-26 21:09:47.927078+0400 pdfKitTest[3163:93151] *** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan nan]'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e2326fb __exceptionPreprocess + 331
1 libobjc.A.dylib 0x000000010c8daac5 objc_exception_throw + 48
2 CoreFoundation 0x000000010e232555 +[NSException raise:format:] + 197
3 QuartzCore 0x00000001112d52ae _ZN2CA5Layer12set_positionERKNS_4Vec2IdEEb + 140
4 QuartzCore 0x00000001112c468b -[CALayer setPosition:] + 57
5 QuartzCore 0x00000001112c4de3 -[CALayer setFrame:] + 560
6 PDFKit 0x000000010c059097 -[PDFPageLayerTile initWithFrame:forPageLayer:withRenderingTransform:tileContentsScale:generationID:] + 168
7 PDFKit 0x000000010c05e805 -[PDFPageLayer _updateTiles] + 3439
8 PDFKit 0x000000010c059d8e -[PDFPageLayer setNeedsTilesUpdate] + 87
9 PDFKit 0x000000010c06e97d -[PDFPageView setNeedsTilesUpdate] + 48
10 PDFKit 0x000000010c070816 -[PDFPageView setFrame:] + 334
11 PDFKit 0x000000010c06711c -[PDFDocumentView createPageViewForPageAtIndex:] + 764
12 PDFKit 0x000000010c068326 -[PDFDocumentView updateVisibility] + 1726
13 PDFKit 0x000000010c0d776f -[PDFView resizeDisplayView:] + 517
14 PDFKit 0x000000010c0d0cdf -[PDFView layoutDocumentView] + 464
15 PDFKit 0x000000010c0cc36a -[PDFView setDocument:waitDuration:] + 1246
16 pdfKitTest 0x000000010bd277e2 $s10pdfKitTest14ViewControllerC11viewDidLoadyyF + 1506
17 pdfKitTest 0x000000010bd27924 $s10pdfKitTest14ViewControllerC11viewDidLoadyyFTo + 36
18 UIKitCore 0x0000000112fda43b -[UIViewController loadViewIfRequired] + 1183
19 UIKitCore 0x0000000112fda868 -[UIViewController view] + 27
20 UIKitCore 0x0000000113612c33 -[UIWindow addRootViewControllerViewIfPossible] + 122
21 UIKitCore 0x0000000113613327 -[UIWindow _setHidden:forced:] + 289
22 UIKitCore 0x0000000113625f86 -[UIWindow makeKeyAndVisible] + 42
23 UIKitCore 0x00000001135d5f1c -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4555
24 UIKitCore 0x00000001135db0c6 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1617
25 UIKitCore 0x0000000112e206d6 __111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 904
26 UIKitCore 0x0000000112e28fce +[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
27 UIKitCore 0x0000000112e202ec -[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 236
28 UIKitCore 0x0000000112e20c48 -[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 1091
29 UIKitCore 0x0000000112e1efba __82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 782
30 UIKitCore 0x0000000112e1ec71 -[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 433
31 UIKitCore 0x0000000112e239b6 __125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 576
32 UIKitCore 0x0000000112e24610 _performActionsWithDelayForTransitionContext + 100
33 UIKitCore 0x0000000112e2371d -[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 223
34 UIKitCore 0x0000000112e286d0 -[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 392
35 UIKitCore 0x00000001135d99a8 -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 514
36 UIKitCore 0x0000000113190dfa -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 361
37 FrontBoardServices 0x00000001194cd125 -[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 448
38 FrontBoardServices 0x00000001194d6ed6 __56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 283
39 FrontBoardServices 0x00000001194d6700 __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 53
40 libdispatch.dylib 0x000000010f5c5db5 _dispatch_client_callout + 8
41 libdispatch.dylib 0x000000010f5c92ba _dispatch_block_invoke_direct + 300
42 FrontBoardServices 0x0000000119508146 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
43 FrontBoardServices 0x0000000119507dfe -[FBSSerialQueue _performNext] + 451
44 FrontBoardServices 0x0000000119508393 -[FBSSerialQueue _performNextFromRunLoopSource] + 42
45 CoreFoundation 0x000000010e199be1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
46 CoreFoundation 0x000000010e199463 __CFRunLoopDoSources0 + 243
47 CoreFoundation 0x000000010e193b1f __CFRunLoopRun + 1231
48 CoreFoundation 0x000000010e193302 CFRunLoopRunSpecific + 626
49 GraphicsServices 0x00000001166b42fe GSEventRunModal + 65
50 UIKitCore 0x00000001135dcba2 UIApplicationMain + 140
51 pdfKitTest 0x000000010bd28a7b main + 75
52 libdyld.dylib 0x000000010f63a541 start + 1
53 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
如果我评论这一行:
pdfView.document = pdfDocument
应用程序没有崩溃,但当然也没有显示 pdf 文件。如何解决这个问题?
我建议(只是猜测)也许 viewDidLoad
还为时过早。该视图还不在视图层次结构中,因此有些事情您不能做。错误是抱怨层没有位置,这是有道理的,因为它没有超级层。
要确认这是问题所在,请尝试将所有代码移至 viewDidAppear
。如果崩溃消失,我们就在正确的轨道上。然后,如果需要,您可以尝试将其移动到一些更好的事件中。我会建议 viewDidLayoutSubviews
。您将需要确保代码不会 运行 多次(使用 Bool 实例 属性 作为标志)。
作为替代方案,我想指出您也可以通过避免在 viewDidLayoutSubviews
之前为 PDFView 设置框架来解决(/hack)这个问题(通过:Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan nan]')。我猜这会延迟调用,否则会导致崩溃。
这在移动 pdfView.document = pdfDocument
很麻烦时很有用,因为例如 PDFView 准备发生在 Viewcontroller 之外。 (就我个人而言,我不得不更改程序的整个结构以在 viewDidLayoutSubviews 中执行文档设置)。
简而言之,更改后:
self.pdfView = PDFView(frame: containerFrame)
对此:
self.pdfView = PDFView()
我可以设置 pdfView.document
而不会导致应用程序崩溃。
对我来说,将 PDFView 代码从 "viewDidLoad" 移动到 "viewDidAppear()" 并没有解决问题!在故事板中创建的 PDFView 带有视图 -> Class: "PDFView".
移动到 "viewDidLayoutSubviews()"(使用布尔标志来检测多个调用)DID 解决了这个问题。
另外:出于同样的原因,github 来自 Vipul 的 PDFKitDemo 示例代码从 12/19/17 开始在我的 xcode 10.2.1 环境中崩溃,因为 PDFView 处理在 "viewDidLoad" 也在此示例代码中!
现在可以使用的代码片段如下:
[...]
var pdfInit : Bool = false
override func viewDidLayoutSubviews() {
if (!pdfInit) {
pdfInit = true;
let documentsUrl:URL = getDocumentsDirectory()
let pdfFileUrl = documentsUrl.appendingPathComponent("test1.pdf")
if let myDocument = PDFDocument(url: pdfFileUrl) {
pdfView.displayMode = .singlePageContinuous
pdfView.document = myDocument
}
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
[...]
当我尝试使用 pdfkit 显示 pdf 文件时,应用程序崩溃了。这是简单的例子 :
import UIKit
import PDFKit
class ViewController: UIViewController {
@IBOutlet weak var pdfView: PDFView!
override func viewDidLoad() {
super.viewDidLoad()
if let path = Bundle.main.path(forResource: "file", ofType: "pdf") {
let url = URL(fileURLWithPath: path)
if let pdfDocument = PDFDocument(url: url) {
pdfView.displayMode = .singlePageContinuous
pdfView.autoScales = true
// pdfView.displayDirection = .horizontal
pdfView.document = pdfDocument
}
}
}
}
这与 "uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan nan]'" 一起崩溃:
2019-03-26 21:09:47.837837+0400 pdfKitTest[3163:93151] libMobileGestalt MobileGestalt.c:890: MGIsDeviceOneOfType is not supported on this platform.
2019-03-26 21:09:47.927078+0400 pdfKitTest[3163:93151] *** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan nan]'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e2326fb __exceptionPreprocess + 331
1 libobjc.A.dylib 0x000000010c8daac5 objc_exception_throw + 48
2 CoreFoundation 0x000000010e232555 +[NSException raise:format:] + 197
3 QuartzCore 0x00000001112d52ae _ZN2CA5Layer12set_positionERKNS_4Vec2IdEEb + 140
4 QuartzCore 0x00000001112c468b -[CALayer setPosition:] + 57
5 QuartzCore 0x00000001112c4de3 -[CALayer setFrame:] + 560
6 PDFKit 0x000000010c059097 -[PDFPageLayerTile initWithFrame:forPageLayer:withRenderingTransform:tileContentsScale:generationID:] + 168
7 PDFKit 0x000000010c05e805 -[PDFPageLayer _updateTiles] + 3439
8 PDFKit 0x000000010c059d8e -[PDFPageLayer setNeedsTilesUpdate] + 87
9 PDFKit 0x000000010c06e97d -[PDFPageView setNeedsTilesUpdate] + 48
10 PDFKit 0x000000010c070816 -[PDFPageView setFrame:] + 334
11 PDFKit 0x000000010c06711c -[PDFDocumentView createPageViewForPageAtIndex:] + 764
12 PDFKit 0x000000010c068326 -[PDFDocumentView updateVisibility] + 1726
13 PDFKit 0x000000010c0d776f -[PDFView resizeDisplayView:] + 517
14 PDFKit 0x000000010c0d0cdf -[PDFView layoutDocumentView] + 464
15 PDFKit 0x000000010c0cc36a -[PDFView setDocument:waitDuration:] + 1246
16 pdfKitTest 0x000000010bd277e2 $s10pdfKitTest14ViewControllerC11viewDidLoadyyF + 1506
17 pdfKitTest 0x000000010bd27924 $s10pdfKitTest14ViewControllerC11viewDidLoadyyFTo + 36
18 UIKitCore 0x0000000112fda43b -[UIViewController loadViewIfRequired] + 1183
19 UIKitCore 0x0000000112fda868 -[UIViewController view] + 27
20 UIKitCore 0x0000000113612c33 -[UIWindow addRootViewControllerViewIfPossible] + 122
21 UIKitCore 0x0000000113613327 -[UIWindow _setHidden:forced:] + 289
22 UIKitCore 0x0000000113625f86 -[UIWindow makeKeyAndVisible] + 42
23 UIKitCore 0x00000001135d5f1c -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4555
24 UIKitCore 0x00000001135db0c6 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1617
25 UIKitCore 0x0000000112e206d6 __111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 904
26 UIKitCore 0x0000000112e28fce +[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
27 UIKitCore 0x0000000112e202ec -[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 236
28 UIKitCore 0x0000000112e20c48 -[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 1091
29 UIKitCore 0x0000000112e1efba __82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 782
30 UIKitCore 0x0000000112e1ec71 -[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 433
31 UIKitCore 0x0000000112e239b6 __125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 576
32 UIKitCore 0x0000000112e24610 _performActionsWithDelayForTransitionContext + 100
33 UIKitCore 0x0000000112e2371d -[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 223
34 UIKitCore 0x0000000112e286d0 -[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 392
35 UIKitCore 0x00000001135d99a8 -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 514
36 UIKitCore 0x0000000113190dfa -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 361
37 FrontBoardServices 0x00000001194cd125 -[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 448
38 FrontBoardServices 0x00000001194d6ed6 __56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 283
39 FrontBoardServices 0x00000001194d6700 __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 53
40 libdispatch.dylib 0x000000010f5c5db5 _dispatch_client_callout + 8
41 libdispatch.dylib 0x000000010f5c92ba _dispatch_block_invoke_direct + 300
42 FrontBoardServices 0x0000000119508146 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
43 FrontBoardServices 0x0000000119507dfe -[FBSSerialQueue _performNext] + 451
44 FrontBoardServices 0x0000000119508393 -[FBSSerialQueue _performNextFromRunLoopSource] + 42
45 CoreFoundation 0x000000010e199be1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
46 CoreFoundation 0x000000010e199463 __CFRunLoopDoSources0 + 243
47 CoreFoundation 0x000000010e193b1f __CFRunLoopRun + 1231
48 CoreFoundation 0x000000010e193302 CFRunLoopRunSpecific + 626
49 GraphicsServices 0x00000001166b42fe GSEventRunModal + 65
50 UIKitCore 0x00000001135dcba2 UIApplicationMain + 140
51 pdfKitTest 0x000000010bd28a7b main + 75
52 libdyld.dylib 0x000000010f63a541 start + 1
53 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
如果我评论这一行:
pdfView.document = pdfDocument
应用程序没有崩溃,但当然也没有显示 pdf 文件。如何解决这个问题?
我建议(只是猜测)也许 viewDidLoad
还为时过早。该视图还不在视图层次结构中,因此有些事情您不能做。错误是抱怨层没有位置,这是有道理的,因为它没有超级层。
要确认这是问题所在,请尝试将所有代码移至 viewDidAppear
。如果崩溃消失,我们就在正确的轨道上。然后,如果需要,您可以尝试将其移动到一些更好的事件中。我会建议 viewDidLayoutSubviews
。您将需要确保代码不会 运行 多次(使用 Bool 实例 属性 作为标志)。
作为替代方案,我想指出您也可以通过避免在 viewDidLayoutSubviews
之前为 PDFView 设置框架来解决(/hack)这个问题(通过:Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer position contains NaN: [nan nan]')。我猜这会延迟调用,否则会导致崩溃。
这在移动 pdfView.document = pdfDocument
很麻烦时很有用,因为例如 PDFView 准备发生在 Viewcontroller 之外。 (就我个人而言,我不得不更改程序的整个结构以在 viewDidLayoutSubviews 中执行文档设置)。
简而言之,更改后:
self.pdfView = PDFView(frame: containerFrame)
对此:
self.pdfView = PDFView()
我可以设置 pdfView.document
而不会导致应用程序崩溃。
对我来说,将 PDFView 代码从 "viewDidLoad" 移动到 "viewDidAppear()" 并没有解决问题!在故事板中创建的 PDFView 带有视图 -> Class: "PDFView".
移动到 "viewDidLayoutSubviews()"(使用布尔标志来检测多个调用)DID 解决了这个问题。
另外:出于同样的原因,github 来自 Vipul 的 PDFKitDemo 示例代码从 12/19/17 开始在我的 xcode 10.2.1 环境中崩溃,因为 PDFView 处理在 "viewDidLoad" 也在此示例代码中!
现在可以使用的代码片段如下:
[...]
var pdfInit : Bool = false
override func viewDidLayoutSubviews() {
if (!pdfInit) {
pdfInit = true;
let documentsUrl:URL = getDocumentsDirectory()
let pdfFileUrl = documentsUrl.appendingPathComponent("test1.pdf")
if let myDocument = PDFDocument(url: pdfFileUrl) {
pdfView.displayMode = .singlePageContinuous
pdfView.document = myDocument
}
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
[...]