在iOS应用程序中自动登录不需要';无法在AppDelegate中100%工作。Delegate使用选项完成启动

在iOS应用程序中自动登录不需要';无法在AppDelegate中100%工作。Delegate使用选项完成启动,ios,objective-c,login,appdelegate,Ios,Objective C,Login,Appdelegate,我的appdelegate中有代码,可以检查用户的凭据是否存储在singleton对象的dictionary属性(从keychain加载)中,如果是,它会自动将其登录。在您关闭应用程序并稍后将其重新打开后,大约50次中有1次,它不会自动让您登录,只会将您带到我们的登录/注册viewcontroller。我知道,如果你重新关闭应用程序并重新打开,它会让你正常登录 我认为有两件事会导致这个问题: 我能重现这种情况的唯一方法是关闭网络连接。因此,有没有任何原因可以解释为什么appdelegate di

我的appdelegate中有代码,可以检查用户的凭据是否存储在singleton对象的dictionary属性(从keychain加载)中,如果是,它会自动将其登录。在您关闭应用程序并稍后将其重新打开后,大约50次中有1次,它不会自动让您登录,只会将您带到我们的登录/注册viewcontroller。我知道,如果你重新关闭应用程序并重新打开,它会让你正常登录

我认为有两件事会导致这个问题:

  • 我能重现这种情况的唯一方法是关闭网络连接。因此,有没有任何原因可以解释为什么appdelegate didFinishLaunchingWithOptions的登录api调用在2%的时间内不起作用

  • 如果由于某些原因,在应用程序代理中,我有2%的时间无法访问钥匙链

  • 如果我的单例代码有问题,从init上的keychain加载的dictionary对象不可用

  • 作为备份,我在登录/启动页面上添加了一个计时器,用于重新ping我们的服务器以查看它们是否已登录,但这似乎没有必要

    这是我的单例对象:

    @interface ABCLoginState ()
    @property (strong) NSDictionary *dict;
    @end
    
    @implementation ABCLoginState
    
    - (id)init
    {
        if (nil != (self = [super init])) {
            self.dict = ABCGetLoginInformation();
        }
        return self;
    }
    
    + (ABCLoginState *)shared
    {
        static dispatch_once_t onceToken;
        static ABCLoginState *loginState;
        dispatch_once(&onceToken, ^{
            loginState = [[ABCLoginState alloc] init];
        });
        return loginState;
    }
    
    - (BOOL)hasLoginData
    {
        return self.dict != nil;
    }
    
    这是我在手机上保存登录凭据的方式:

    NSDictionary *ABCGetLoginInformation()
    {
    NSDictionary *d;
    d = @{ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
           (__bridge id)kSecAttrService: SECSERVICENAME,
           (__bridge id)kSecReturnAttributes: (__bridge id)kCFBooleanTrue,
           (__bridge id)kSecReturnData: (__bridge id)kCFBooleanTrue };
    CFDictionaryRef found = nil;
    SecItemCopyMatching((__bridge CFDictionaryRef)d, (CFTypeRef *)&found);
    
    if (!found) {
        /*
         *  No credentials.
         */
    
        return nil;
    } else {
        /*
         *  We found a username and password. Return them
         */
    
        NSDictionary *data = (__bridge_transfer NSDictionary *)found;
        NSString *username = (NSString *)[data objectForKey:(__bridge id)kSecAttrAccount];
        NSString *password = [[NSString alloc] initWithData:[data objectForKey:(__bridge id)kSecValueData] encoding:NSUTF8StringEncoding];
    
        NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
        NSInteger userID = [ud integerForKey:@"UserID"];
    
        return @{ @"username": username, @"password": password, @"userid": @( userID ) };
    }
    }
    

    谢谢

    另一个潜在的问题可能是当应用程序处于后台并被移动到挂起状态到未运行状态时。当它达到这种状态时,它会以某种方式重置应用程序?如果你延迟一点(2秒左右)访问钥匙链会发生什么。E通过运行循环分派代码?尚未尝试,但将尝试。这是一个需要调试的棘手问题,因为它似乎不会给我带来问题,除非应用程序在后台运行了很多小时(例如,这通常发生在我早上重新打开应用程序时)。@Hawk您是否尝试过检查
    protectedDataAvailable
    :bool?如果您的手机有pin码,钥匙链可能会锁定到您的应用程序一段时间。我猜延迟与iCloud同步钥匙链有关?另外,请查看
    UIApplicationProtectedDataDidBecomeAvailable
    :@mattyice这正是我所想的:它被保护了一会儿。