我发布的应用程序使用CFUUID
和SSKeychain
来识别设备(即使应用程序已卸载并重新安装,也可以保持该ID不变)
我将这些设备ID保存在服务器中,我最近注意到某些用户拥有同一个真实设备的多个ID。我看到的唯一解释是ID没有从Keychain保存或加载,因此设备生成一个新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
因某些原因无法正常工作。稍后在应用程序中,我注册了推送通知,并将推送令牌与我用相同的确切行[SSKeychain passwordForService:serviceName account:identifier]
读取的CFUUID一起发送到服务器,但是当它被发送到服务器时它不是零(所以我可以看到几个具有相同推送令牌的CFUUID。)
编辑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"
}
]
我看到2个可能导致奇怪行为的候选者,控制器主体中的NSStrings
和静态getDevice
方法。但是,我不知道这在许多设备中如何工作,但在其他设备中却失败了。
答案 0 :(得分:7)
我遇到了同样的问题,我找到了解决方案。用户将密码设置为解锁手机的设备会出现问题。在iOS7上,某些代码可以在后台运行(推送通知,后台获取),如果您使用标准辅助功能类型在钥匙串中保存了某些内容,则在设备被锁定(并且应用程序在后台运行)时无法读取它。尝试设置:
[SSKeychain setAccessibilityType:kSecAttrAccessibleAlways];
在读/写钥匙串之前。 希望它有所帮助。
答案 1 :(得分:0)
NSString * retrieveuuid = [SSKeychain passwordForService:serviceName 帐户:标识符];
retrieveuuid取决于服务,女巫总是一样的,但它也取决于帐户。我认为您的问题是一个用户可以在同一个设备中拥有多个帐户,然后您的代码会为每个帐户生成一个UUID。