2017-03-22 14 views
1

내 앱은 여러 클라우드 서비스 (보관 용 계정, Google 드라이브 등)의 승인을 지원하며 적절한 SDK를 사용합니다. 모든 SDK는 사용자가 자격 증명을 입력 할 수있는 웹보기를 제공하여 인증을 제공합니다. 이 문제는 웹 뷰는 다음과 같은 상황에서 응용 프로그램을 중단한다는 것입니다 :텍스트 필드를 탭하고 키보드를 닫은 다음 텍스트 필드를 다시 누르면 UIWebView 충돌이 발생합니다.

  1. 현재 웹보기
  2. 텍스트 필드에 버튼
  3. 탭을 "완료"의 모든
  4. 키보드가 나타나면 텍스트 필드, 버튼을 누르세요
  5. 탭 2 단계
  6. 충돌

다음 정보 탭이 콘솔에 인쇄됩니다.

2017-03-22 19:17:55.564 MyApplicationName[46315:16017957] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil' 
*** First throw call stack: 
(
    0 CoreFoundation      0x000000010e63ff65 __exceptionPreprocess + 165 
    1 libobjc.A.dylib      0x0000000111960deb objc_exception_throw + 48 
    2 CoreFoundation      0x000000010e506f55 -[__NSArrayM insertObject:atIndex:] + 901 
    3 UIKit        0x000000011206fcd4 -[UIViewController _addChildViewController:performHierarchyCheck:notifyWillMove:] + 541 
    4 UIKit        0x00000001127e9581 -[UIInputWindowController changeToInputViewSet:] + 1420 
    5 UIKit        0x00000001127e218f -[UIInputWindowController moveFromPlacement:toPlacement:starting:completion:] + 369 
    6 UIKit        0x00000001127ea01b -[UIInputWindowController setInputViewSet:] + 983 
    7 UIKit        0x00000001127e1e17 -[UIInputWindowController performOperations:withAnimationStyle:] + 50 
    8 UIKit        0x00000001124fb397 -[UIPeripheralHost(UIKitInternal) setInputViews:animationStyle:] + 1275 
    9 UIKit        0x00000001120e0c89 -[UIResponder(UIResponderInputViewAdditions) reloadInputViews] + 81 
    10 UIKit        0x0000000112527604 -[UIWebBrowserView _reloadInputViewsAfterPotentialFocusRedirect] + 54 
    11 UIKit        0x00000001125274a9 -[UIWebBrowserView _endAllowingFocusRedirects] + 45 
    12 libdispatch.dylib     0x00000001149d149b _dispatch_client_callout + 8 
    13 libdispatch.dylib     0x00000001149bacd8 _dispatch_barrier_sync_f_slow_invoke + 284 
    14 libdispatch.dylib     0x00000001149d149b _dispatch_client_callout + 8 
    15 libdispatch.dylib     0x00000001149b934b _dispatch_main_queue_callback_4CF + 1738 
    16 CoreFoundation      0x000000010e5a03e9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9 
    17 CoreFoundation      0x000000010e561939 __CFRunLoopRun + 2073 
    18 CoreFoundation      0x000000010e560e98 CFRunLoopRunSpecific + 488 
    19 GraphicsServices     0x0000000115eafad2 GSEventRunModal + 161 
    20 UIKit        0x0000000111ee0676 UIApplicationMain + 171 
    21 MyApplicationName     0x000000010c161682 main + 114 
    22 libdyld.dylib      0x0000000114a0592d start + 1 
    23 ???         0x0000000000000001 0x0 + 1 
) 
libc++abi.dylib: terminating with uncaught exception of type NSException 

분명히하는 텍스트 필드를 탭하면 문제가 나타납니다, 그래서 나는 단순히 google.com 열고 응용 프로그램 충돌 것입니다 있는지 확인하기 위해, 거기에 텍스트 필드에 눌러 테스트하기로 결정했다. 응용 프로그램이 충돌하지 않았지만 키보드를 표시하거나 숨길 때 다음 정보가 인쇄되었습니다.

2017-03-22 20:31:52.453 MyApplicationName[55324:16092779] *** WebKit discarded an uncaught exception in the webView:elementDidFocusNode: delegate: <NSInvalidArgumentException> *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil 
2017-03-22 20:31:54.985 MyApplicationName[55324:16092779] *** WebKit discarded an uncaught exception in the webView:elementDidBlurNode: delegate: <NSInvalidArgumentException> *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil 
2017-03-22 20:31:56.341 MyApplicationName[55324:16092779] *** WebKit discarded an uncaught exception in the webView:elementDidFocusNode: delegate: <NSInvalidArgumentException> *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil 
2017-03-22 20:31:58.029 MyApplicationName[55324:16092779] *** WebKit discarded an uncaught exception in the webView:elementDidBlurNode: delegate: <NSInvalidArgumentException> *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil 
2017-03-22 20:32:00.675 MyApplicationName[55324:16092779] *** WebKit discarded an uncaught exception in the webView:elementDidFocusNode: delegate: <NSInvalidArgumentException> *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil 
2017-03-22 20:32:02.872 MyApplicationName[55324:16092779] *** WebKit discarded an uncaught exception in the webView:elementDidBlurNode: delegate: <NSInvalidArgumentException> *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil 

내가 거기 당신이 this gif를 살펴 경우, 해당 도구 모음이 처음으로 나타납니다 알 수 있기 때문에, 키보드의 도구 모음에 일부 문제가 있지만, 두 번째로 나타나지 않고 QuickType가 나타납니다 의심 짧은 순간.

추가 정보 : - 샘플 프로젝트에서 문제를 재현 할 수 없습니다. google.com에서 응용 프로그램을 중단하려고 시도 할 때 로그에 오류나 오류가 없었습니다. - UIWindow에 일부 제스처 인식기가있을 가능성은 거의 없습니다.

그래서 질문입니다. 어떻게 수정해야합니까?

답변

1

UIInputWindowController의 changeToInputViewSet에서 하위보기 컨트롤러를 추가하려고하는데 하위보기 컨트롤러가 nil입니다. 귀하의보기 컨트롤러가 무효 인 이유를 찾아서 수정하십시오. 충돌이있는 반복적 인 순서가 있습니다. changeToInputViewSet의 시작 부분에 중단 점을 넣고 사용중인 viewController의 값을 관찰합니다. 당신 버그가 있습니다.

+0

저는 버그를 가져온 커밋을 찾아서 버그의 원인을 찾아서 대답을 게시했습니다. 하지만 어쨌든 당신의 의견을 보내 주셔서 감사합니다! – xinatanil

0

좋아, 그래서이 문제의 원인을 파악할 수있었습니다. 아래의이 작은 확장 프로그램이 버그를 일으켰습니다.

extension UIViewController { 
    /** 
    Simple shortcut for trivial cases. 
    Adds a child controller to the view, that is a descendant of `self.view`. 
    By default, child controller's view is stretched in the passed view. 
    Use `constraintsSetupBlock` to setup constraints as you need. 
    */ 
    func addChildViewController(childController: UIViewController, to view: UIView, constraintsSetupBlock: ((view: UIView, childControllerView: UIView) -> Void)? = nil) { 
     guard view.isDescendantOfView(self.view) else { 
      fatalError("`view` must be a descendand of `self.view`") 
     } 

     addChildViewController(childController) 
     view.addSubview(childController.view) 
     if let setupBlock = constraintsSetupBlock { 
      setupBlock(view: view, childControllerView: childController.view) 
     } else { 
      childController.view.snp_makeConstraints(closure: { (make) in 
       make.edges.equalTo(view) 
      }) 
     } 
     childController.didMoveToParentViewController(self) 
    } 

    /** 
    Simple shortcut for trivial cases. 
    `childController` is optional purely for convenience. 
    */ 
    func removeChildViewController(childController: UIViewController?) { 
     guard let controller = childController else { return } 
     controller.willMoveToParentViewController(nil) 
     controller.view.removeFromSuperview() 
     controller.didMoveToParentViewController(nil) 
    } 
} 

내 생각 엔 어떤 SDK의 개인 방법과 일치하는 방법 이름, 실행시 시스템이 매우 불쾌한 결과를 이끌어 내 구현을 선택한다는 것입니다.