3

私の公開アプリケーションは、デバイスを識別するためにCFUUIDandを使用します (また、アプリがアンインストールされて再インストールされても、その ID は変更されません)。SSKeychain

私はそれらのデバイス ID をサーバーに保存していますが、最近、一部のユーザーが同じ実際のデバイスに対してこれらの ID を複数持っていることに気付きました。私が見る唯一の説明は、ID がキーチェーンから保存またはロードされていないため、デバイスが新しい ID を生成するということです。奇妙なことに、同じ iOS バージョンを実行している他のデバイスでも問題なく動作します。

何が起こっているのかについてのアイデアはありますか?

これは私の関連コードです(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

NSString* identifier = @"appName";
NSString* serviceName = @"com.company.appName";
NSString *retrieveuuid = [SSKeychain passwordForService:serviceName account:identifier];
if (retrieveuuid == nil) {
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    NSString *uuid  = (NSString*) string;
    [SSKeychain setPassword:uuid forService:serviceName account:identifier];
}

編集:retrieveuuid == nil何らかの理由で期待どおりに機能していないと思います。アプリの後半でプッシュ通知を登録し、まったく同じ行で読み取ったこのCFUUIDとともにプッシュトークンをサーバーに送信し[SSKeychain passwordForService:serviceName account:identifier]ますが、サーバーに送信されるとnilではありません(したがって、同じプッシュ トークン)。

EDIT 2 を追加して、実際のコードを追加します。

AppDelegate.m

NSString* identifier = @"appName";
NSString* serviceName = @"com.company.appName";
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //Creating UUID
    NSString *retrieveuuid = [AppDelegate getDeviceId];
    if (retrieveuuid == nil) {
        CFUUIDRef theUUID = CFUUIDCreate(NULL);
        CFStringRef string = CFUUIDCreateString(NULL, theUUID);
        CFRelease(theUUID);
        NSString *uuid  = (NSString*) string;
        [SSKeychain setPassword:uuid forService:serviceName account:identifier];
    }

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}

+ (NSString*) getDeviceId {
    return [SSKeychain passwordForService:serviceName account:identifier];
}

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
    NSString *newToken = [deviceToken description];
    newToken = [newToken stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    newToken = [newToken stringByReplacingOccurrencesOfString:@" " withString:@""];

    _deviceToken = [[NSString alloc] initWithString:newToken];

    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
    NSString *user = [prefs objectForKey:@"appNameUsername"];

    if(user && ![user isEqualToString:@""]){
        RestClient *rest = [[RestClient alloc] init];
        rest.delegate = self;
        rest.tag = 2;
        [rest updateToken:newToken ForUsername:user];
        [rest release];
    }
}

RestClient.m

-(void) updateToken:(NSString *)token ForUsername:(NSString *)userName{
    NSArray* info = [NSArray arrayWithObject: [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                               userName, @"Username",
                                               token, @"TokenNo",
                                               [[UIDevice currentDevice].model hasPrefix:@"iPad"] ? @"iPad" : @"iPhone", @"Device",
                                               [UIDevice currentDevice].systemVersion, @"OSVersion",
                                               [AppDelegate getDeviceId], @"DeviceID",
                                               @"updateToken", @"CMD",
                                               nil]];
    [self doAction:info];
}

doAction メソッドはデータをサーバーに送信し、デリゲートをコールバックするだけで、その部分は正常に機能します。このコマンドを受信したログをサーバーで確認できます。

"JSONCMD":"[
{   "TokenNo" : "f0d3aa21758350333b7e6315c38_EDIT_257c1838f49c43049f8380ec1ff63", 
    "AppVersion" : "1.0.4",
    "Username" : "user@server.com", 
    "CMD" : "updateToken", 
    "OSVersion" : "7.0.4", 
    "DeviceID" : "9B794E11-6EF7-470C-B319-5A9FCCDAFD2B", 
    "Device" : "iPhone"
}
]  

NSStringsコントローラー本体と静的getDeviceメソッドの2つの候補が奇妙な動作を引き起こしている可能性があります。ただし、これが多くのデバイスでどのように機能するかはわかりませんが、他のデバイスでは失敗します。

4

2 に答える 2

7

私は同じ問題を抱えていて、解決策を見つけました。この問題は、ユーザーが電話のロックを解除するようにパスコードを設定しているデバイスで発生します。iOS7 では、一部のコードはバックグラウンドで実行できます (プッシュ通知、バックグラウンド フェッチ)。標準のアクセシビリティ タイプでキーチェーンに何かを保存すると、デバイスがロックされている (そしてアプリがバックグラウンドで実行されている) ときにそれを読み取ることができません。これを設定してみてください:

[SSKeychain setAccessibilityType:kSecAttrAccessibleAlways];

キーチェーンを読み書きする前に。それが役に立てば幸い。

于 2014-04-10T05:44:58.843 に答える