iOS Appcelerator Facebook 登录 - 登录事件不会在设备上触发

iOS Appcelerator Facebook Login - Login Event Doesn't Fire on Device

尝试在我的应用程序中登录 Facebook 时,我遇到了一些奇怪的行为。

当前堆栈信息:

  1. Appcelerator 6.0.1.GA
  2. Appcelerator CLI 6.1.0
  3. iOS10.1
  4. xCode8.2.1

奇怪的行为:

  1. login 从设备上的 Facebook 登录返回时,事件从不触发。
  2. login 在模拟器上从 Facebook 登录返回时,事件有时不会触发。
  3. 设置 facebook.LOGIN_BEHAVIOR_NATIVE 仍会尝试在设备上使用浏览器登录,有时
  4. 有时在设备上,应用切换器会打开 Facebook 应用 浏览器进行登录。挺烦人的。

我实际上是该模块 setLoginBehavior 功能的原始贡献者,尽管 Facebook 的立场似乎在贡献从 "We always want you to use browser." 到 "We always want you to use Native." 后发生了变化。我在这里发布这个问题,以防有人有一些见解 - 在我等待答案的同时,我将回到该模块的源代码中。

我能想到的与大多数应用程序不同的唯一因素是我正在使用 Kris Kowals Q。下面是代码,几乎是从我的应用程序中逐字记录的。

实际执行登录的函数:

// linkingmodule.js
exports.linkFacebook = function() {
    var Q = require('vendor/q'),
        response = Q.defer(),
        facebook = require('facebook'),
        permissions = ['public_profile', 'user_friends', 'user_likes'];  

    facebook.initialize();
    facebook.setLoginBehavior(facebook.LOGIN_BEHAVIOR_NATIVE);
    facebook.permissions = permissions;

    facebook.addEventListener('login', function fireLogin(e) {
        if(!e.success || !facebook.loggedIn) {
            return response.reject({
                status: e.code,
                error: e.error
            });
        }

        response.resolve({
            uid: e.uid,
            data: e.data,
            token: facebook.getAccessToken()
        });
    });

    facebook.authorize();
    return response.promise;
};

调用登录函数的alloy控制器函数:

// login.js
function facebookLogin() {
    var remote = require('linkingmodule');

    remote.linkFacebook().
    then(function(r) {
            // do some things
        }).
        fail(function(e) {
            console.error(e);
            throw 'Unable to login with Facebook.';
        });
    }).
    fail(function(e) {
        console.error('Facebook login failed');
        console.error(e);
    });
}

我已将其归因于 Titanium 模块 SDK 中的错误,特别是 Ti.fireEvent。我的调查以 Facebook 模块结束,但模块内的所有事件似乎都按预期发送和接收。只是,当Ti.fireEvent被调用时,在JS应用"under some circumstances"中没有收到。 facebook 模块中仍然存在 block retain cycle 的可能性,但我无法解决它。

这是我的解决方法:

function facebookLogin() {
    var Q = require('vendor/q'),
        response = Q.defer(),
        fb = require('facebook'),
        permissions = ['public_profile', 'user_friends', 'user_likes'];  

    var checkLoginStatus, fireLogin;

    checkLoginStatus = function(e) {
        Ti.App.removeEventListener('resumed', checkLoginStatus);
        fb.removeEventListener('login', fireLogin);

        // login often doesn't fire, so let's check on resumed as well
        if(fb.loggedIn) {
            return response.resolve({
                uid: fb.uid,
                data: null,
                token: fb.getAccessToken()
            });
        }
        console.log('resumed and found that are NOT logged in');
        return response.reject({
            status: -1,
            error: 'Did not work.'
        });
    };
    fireLogin = function(e) {
        fb.removeEventListener('login', fireLogin);
        Ti.App.removeEventListener('resumed', checkLoginStatus);
        if(!e.success || !fb.loggedIn) {
            return response.reject({
                status: e.code,
                error: e.error
            });
        }

        response.resolve({
            uid: e.uid,
            data: e.data,
            token:fb.getAccessToken()
        });
    };

    Ti.App.addEventListener('resumed', checkLoginStatus);
    fb.addEventListener('login', fireLogin);

    fb.initialize();
    fb.setLoginBehavior(fb.LOGIN_BEHAVIOR_NATIVE);
    fb.permissions = permissions;
    fb.authorize();

    return response.promise;
}

所以,基本上继续监听 login 事件 - 它在 "some circumstances" 下正确触发。但也要听 App.resumed。以先触发者为准,取消所有侦听器,并检查登录状态。