美文网首页项目常见崩溃iOS精选
项目常见崩溃10(陆续更新)

项目常见崩溃10(陆续更新)

作者: bigParis | 来源:发表于2018-08-18 10:37 被阅读95次

做国际化的app, facebook登录是一定少不了的, 今天介绍一种facebook登录引起的崩溃.

先看堆栈

Thread 0 (crashed)
 0  libobjc.A.dylib!objc_msgSend + 0x1c
    Found by: given as instruction pointer in context
 1  SafariServices!__75-[SFAuthenticationViewController dismissViewControllerAnimated:completion:]_block_invoke + 0x1c
    Found by: previous frame's frame pointer
 2  UIKit!-[UIPresentationController transitionDidFinish:] + 0x524
    Found by: previous frame's frame pointer
 3  UIKit!-[_UICurrentContextPresentationController transitionDidFinish:] + 0x28
    Found by: previous frame's frame pointer
 4  UIKit!__56-[UIPresentationController runTransitionForCurrentState]_block_invoke_2 + 0xb8
    Found by: previous frame's frame pointer
 5  UIKit!-[_UIViewControllerTransitionContext completeTransition:] + 0x70
    Found by: previous frame's frame pointer
 6  UIKit!-[UITransitionView notifyDidCompleteTransition:] + 0xf8
    Found by: previous frame's frame pointer
 7  UIKit!-[UITransitionView _didCompleteTransition:] + 0x464
    Found by: previous frame's frame pointer
 8  UIKit!-[UITransitionView _transitionDidStop:finished:] + 0x74
    Found by: previous frame's frame pointer
 9  UIKit!-[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 0x134
    Found by: previous frame's frame pointer
10  UIKit!-[UIViewAnimationState animationDidStop:finished:] + 0x124
    Found by: previous frame's frame pointer
11  UIKit!-[UIViewAnimationState animationDidStop:finished:] + 0x1c4
    Found by: previous frame's frame pointer
12  QuartzCore!CA::Layer::run_animation_callbacks(void*) + 0x118
    Found by: previous frame's frame pointer
13  libdispatch.dylib!_dispatch_client_callout + 0xc
    Found by: previous frame's frame pointer
14  libdispatch.dylib!_dispatch_main_queue_callback_4CF$VARIANT$mp + 0x3f4
    Found by: previous frame's frame pointer
15  CoreFoundation!__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 0x8
    Found by: previous frame's frame pointer
16  CoreFoundation!__CFRunLoopRun + 0x7d8
    Found by: previous frame's frame pointer
17  CoreFoundation!CFRunLoopRunSpecific + 0x1b0
    Found by: previous frame's frame pointer
18  GraphicsServices!GSEventRunModal + 0x60
    Found by: previous frame's frame pointer
19  UIKit!UIApplicationMain + 0xcc
    Found by: previous frame's frame pointer
20  Hago!main [main.mm : 18 + 0x10]
    Found by: previous frame's frame pointer
21  libdyld.dylib + 0x1568
    Found by: previous frame's frame pointer

WTF, SFAuthenticationViewController? 好像不是我们的代码哦, 这个实际上是系统的一个VC, 在我们点击facebook登录前, 会引导我们去到一个facebook授权页面, 这个页面就是SFAuthenticationViewController类型的, 在测试中确实很难模拟出这种情况, 因为点击一次登录后就会弹出弹窗, 要我们确认, 这时候按道理是没机会再次点击facebook登录的, 但是如果用户的手机比较卡, 连续点了两次, 但是第二次没传递到按钮时候, 用户已经迫不及待的同意授权, 并唤出SFAuthenticationViewController这时候第二次点击传递到了按钮, 触发了再次弹窗, 这时候再次点击确认就崩溃了.

分析: 我们程序在自动登录的时候, 如果发现facebook不能自动登录(token过期, 概率很小)也会触发弹出弹窗, 但这之前用户如果也点击了facebook登录, 并且点击弹窗的继续, 并且来到SFAuthenticationViewController页面才触发自动登录失败的弹窗, 这时候再次点击弹窗就崩溃了.

代码重现崩溃

- (void)tp_login:(PKTpLoginCallback)callback timeout:(TimeOutHandler)timeout
{
    [self fbNewLogin:callback timeout:timeout];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self fbNewLogin:callback timeout:timeout];
    });
}

在3秒内, 下次弹窗弹出前, 触发弹窗, 并点击继续, 来到SFAuthenticationViewController页面. 3秒到, 再次弹窗, 点击, 崩溃~

还有以下几种堆栈也是类似的问题

Thread 0 (crashed)
 0  libobjc.A.dylib!objc_object::release() + 0x10
    Found by: given as instruction pointer in context
 1  SafariServices!__75-[SFAuthenticationViewController dismissViewControllerAnimated:completion:]_block_invoke + 0x1c
    Found by: previous frame's frame pointer
 2  SafariServices!__75-[SFAuthenticationViewController dismissViewControllerAnimated:completion:]_block_invoke + 0x1c
    Found by: previous frame's frame pointer
 3  UIKit!-[UIPresentationController transitionDidFinish:] + 0x524
    Found by: previous frame's frame pointer
 4  UIKit!-[_UICurrentContextPresentationController transitionDidFinish:] + 0x24
    Found by: previous frame's frame pointer
 5  UIKit!__56-[UIPresentationController runTransitionForCurrentState]_block_invoke.436 + 0xb8
    Found by: previous frame's frame pointer
 6  UIKit!-[_UIViewControllerTransitionContext completeTransition:] + 0x70
    Found by: previous frame's frame pointer
 7  UIKit!-[UITransitionView notifyDidCompleteTransition:] + 0xf8
    Found by: previous frame's frame pointer
 8  UIKit!-[UITransitionView _didCompleteTransition:] + 0x468
    Found by: previous frame's frame pointer
 9  UIKit!-[UITransitionView _transitionDidStop:finished:] + 0x74
    Found by: previous frame's frame pointer
10  UIKit!-[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 0x134
    Found by: previous frame's frame pointer
11  UIKit!-[UIViewAnimationState animationDidStop:finished:] + 0x124
    Found by: previous frame's frame pointer
12  UIKit!-[UIViewAnimationState animationDidStop:finished:] + 0x1c4
    Found by: previous frame's frame pointer
13  QuartzCore!CA::Layer::run_animation_callbacks(void*) + 0x118
    Found by: previous frame's frame pointer
14  libdispatch.dylib!_dispatch_client_callout + 0xc
    Found by: previous frame's frame pointer
15  libdispatch.dylib!_dispatch_main_queue_callback_4CF$VARIANT$mp + 0x3f0
    Found by: previous frame's frame pointer
16  CoreFoundation!__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 0x8
    Found by: previous frame's frame pointer
17  CoreFoundation!__CFRunLoopRun + 0x8dc
    Found by: previous frame's frame pointer
18  CoreFoundation!CFRunLoopRunSpecific + 0x224
    Found by: previous frame's frame pointer
19  GraphicsServices!GSEventRunModal + 0x60
    Found by: previous frame's frame pointer
20  UIKit!UIApplicationMain + 0xe8
    Found by: previous frame's frame pointer
21  Hago!main [main.mm : 18 + 0x10]
    Found by: previous frame's frame pointer
22  libdyld.dylib!start + 0x0
    Found by: previous frame's frame pointer

问题出现在这段代码

FBSDKApplicationDelegate.m
if (@available(iOS 11.0, *)) {
    if ([sender isAuthenticationURL:url]) {
      Class SFAuthenticationSessionClass = fbsdkdfl_SFAuthenticationSessionClass();
      if (SFAuthenticationSessionClass != nil) {
          WEAKIFYSELF
        _authenticationSession = [[SFAuthenticationSessionClass alloc] initWithURL:url callbackURLScheme:[FBSDKInternalUtility appURLScheme] completionHandler:^ (NSURL *aURL, NSError *error) {
          handler(error == nil, error);
            STRONGIFYSELF
          if (error == nil) {
            [self application:[UIApplication sharedApplication] openURL:aURL sourceApplication:@"com.apple" annotation:nil];
          }
          self.authenticationSession = nil;
        }];
        [self.authenticationSession start];
        return;
      }
    }
  }

这里发现是iOS11系统先来一段装B的代码, 就是这段代码造成了后续的崩溃. 这里我的解决办法就是注释掉这段装B的代码, 直接走后面的逻辑. 当然, 还是要直面问题.

stackoverflow已经给出了解决办法.

- (void)tp_login:(PKTpLoginCallback)callback timeout:(TimeOutHandler)timeout
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }
    
    if (![topController isKindOfClass:NSClassFromString(@"SFSafariViewController")])
    {
        [self fbNewLogin:callback timeout:timeout];
    }
}
- (void)fbNewLogin:(PKTpLoginCallback)callback
           timeout:(TimeOutHandler)timeout
{
    [_fbLoginMgr logOut];
    _fbLoginMgr.loginBehavior = FBSDKLoginBehaviorBrowser;
    [_fbLoginMgr logInWithReadPermissions:@[ @"public_profile", @"email", @"user_friends", @"user_birthday", @"user_gender" ] fromViewController:nil handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
        MFLogInfo(LogTag, @"facebook login result.grantedPermissions = %@, error = %@", result.grantedPermissions, error);
        if (error) {
            safetyCallblock(callback, kPKLoginResultTpAuthFailed, error.description, nil);
            MFLogError(LogTag, @"Process error");
        } else if (result.isCancelled) {
            safetyCallblock(callback, kPKLoginResultTpLoginCancel, nil, nil);
            MFLogInfo(LogTag, @"Cancelled");
        } else {
            if (result.token.userID.length > 0) {
                [[NSNotificationCenter defaultCenter] postNotificationName:kPKFbAuthSuccessNotification object:nil userInfo:@{kPKFbAuthInfoKey : result.token.userID}];
            }

            HGTpAuthRes *authInfo = [[HGTpAuthRes alloc] init];
            authInfo.accessToken = result.token.tokenString;
            authInfo.openId = result.token.userID;
            authInfo.tpLoginType = kPKTpLoginTypeFacebook;

            //https://developers.facebook.com/docs/graph-api/reference/user  接口文档

            NSDictionary *parameters = @{ @"fields" : @"id,name,gender,birthday,picture.width(1080).height(1080)" };
            [[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" parameters:parameters] startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
                if (!error && [result isKindOfClass:[NSDictionary class]]) {
                    MFLogInfo(LogTag, @"third parth get userinfo succ");
                    authInfo.tpUserInfo = [self parseUserInfo:result];
                }

                safetyCallblock(callback, kPKLoginResultOk, nil, authInfo);
            }];

            MFLogInfo(LogTag, @"third parth log in succ");
        }
    }];
}

这里在每次调用前都判断下当前present的vc是否是SFSafariViewController的子类, 这样就没问题了, 等待上线看效果.

相关文章

  • 项目常见崩溃10(陆续更新)

    做国际化的app, facebook登录是一定少不了的, 今天介绍一种facebook登录引起的崩溃. 先看堆栈 ...

  • 项目常见崩溃(陆续更新)

    项目中有些崩溃很难重现, 甚至开发者自己根本无法重现, 但是又确实崩溃很多, 只见堆栈, 却无法重现, 这种崩溃着...

  • 项目常见崩溃11(陆续更新)

    做国际化的app, google登录是一定少不了的, 今天介绍一种google登录引起的崩溃. 先看堆栈 在过去3...

  • 项目常见崩溃12(陆续更新)

    说起死锁, 可能很多人都懂其中的原理, 但是却很少有人真正解决甚至遇到过死锁, 最近有幸真的处理了一次死锁. 这次...

  • 项目常见崩溃9(陆续更新)

    循环引用是一个大家熟悉有陌生的东西, 今天的崩溃也和循环引用有点关系. 崩溃堆栈 定位到崩溃所在的93,94行代码...

  • 项目常见崩溃8(陆续更新)

    今天介绍一个WKUIDelegate引起的崩溃 崩溃堆栈 runJavaScriptAlert是关键点, 这里提示...

  • 项目常见崩溃6(陆续更新)

    很多崩溃都是源于低版本的系统, 可能这是系统的bug, 但作为开发人员, 即便是系统的bug, 我们也应该找到崩溃...

  • 项目常见崩溃7(陆续更新)

    今天介绍一个和循环引用很相似的容器类的问题. 崩溃堆栈 异常信息如下 从异常信息上来看是访问一个已经被加锁的NSA...

  • 项目常见崩溃3(陆续更新)

    上回书说animated隐式动画的血与泪, 今天要说的可能和崩溃无关, 但是又是很多诡异的崩溃的根源: 内存泄露....

  • 项目常见崩溃2(陆续更新)

    上回书说AFN多线程崩溃实难重现, 这回的崩溃是不定概率重现的, 今天来说下animated隐式动画的血与泪. 不...

网友评论

    本文标题:项目常见崩溃10(陆续更新)

    本文链接:https://www.haomeiwen.com/subject/ibwxiftx.html