@@ -25,58 +25,58 @@ +(FCUUID *)sharedInstance
25
25
{
26
26
static FCUUID *instance = nil ;
27
27
static dispatch_once_t token;
28
-
28
+
29
29
dispatch_once (&token, ^{
30
30
instance = [[self alloc ] init ];
31
31
});
32
-
32
+
33
33
return instance;
34
34
}
35
35
36
36
37
37
-(instancetype )init
38
38
{
39
39
self = [super init ];
40
-
40
+
41
41
if (self)
42
42
{
43
43
[self uuidsOfUserDevices_iCloudInit ];
44
44
}
45
-
45
+
46
46
return self;
47
47
}
48
48
49
49
50
50
-(NSString *)_getOrCreateValueForKey : (NSString *)key defaultValue : (NSString *)defaultValue userDefaults : (BOOL )userDefaults keychain : (BOOL )keychain service : (NSString *)service accessGroup : (NSString *)accessGroup synchronizable : (BOOL )synchronizable
51
51
{
52
52
NSString *value = [self _getValueForKey: key userDefaults: userDefaults keychain: keychain service: service accessGroup: accessGroup];
53
-
53
+
54
54
if (!value){
55
55
value = defaultValue;
56
56
}
57
-
57
+
58
58
if (!value){
59
59
value = [self uuid ];
60
60
}
61
-
61
+
62
62
[self _setValue: value forKey: key userDefaults: userDefaults keychain: keychain service: service accessGroup: accessGroup synchronizable: synchronizable];
63
-
63
+
64
64
return value;
65
65
}
66
66
67
67
68
68
-(NSString *)_getValueForKey : (NSString *)key userDefaults : (BOOL )userDefaults keychain : (BOOL )keychain service : (NSString *)service accessGroup : (NSString *)accessGroup
69
69
{
70
70
NSString *value = nil ;
71
-
71
+
72
72
if (!value && keychain ){
73
73
value = [UICKeyChainStore stringForKey: key service: service accessGroup: accessGroup];
74
74
}
75
-
75
+
76
76
if (!value && userDefaults ){
77
77
value = [[NSUserDefaults standardUserDefaults ] stringForKey: key];
78
78
}
79
-
79
+
80
80
return value;
81
81
}
82
82
@@ -87,7 +87,7 @@ -(void)_setValue:(NSString *)value forKey:(NSString *)key userDefaults:(BOOL)use
87
87
[[NSUserDefaults standardUserDefaults ] setObject: value forKey: key];
88
88
[[NSUserDefaults standardUserDefaults ] synchronize ];
89
89
}
90
-
90
+
91
91
if ( value && keychain ){
92
92
UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService: service accessGroup: accessGroup];
93
93
[keychain setSynchronizable: synchronizable];
@@ -99,11 +99,11 @@ -(void)_setValue:(NSString *)value forKey:(NSString *)key userDefaults:(BOOL)use
99
99
-(NSString *)uuid
100
100
{
101
101
// also known as uuid/universallyUniqueIdentifier
102
-
102
+
103
103
CFUUIDRef uuidRef = CFUUIDCreate (NULL );
104
104
CFStringRef uuidStringRef = CFUUIDCreateString (NULL , uuidRef);
105
105
CFRelease (uuidRef);
106
-
106
+
107
107
NSString *uuidValue = (__bridge_transfer NSString *)uuidStringRef;
108
108
uuidValue = [uuidValue lowercaseString ];
109
109
uuidValue = [uuidValue stringByReplacingOccurrencesOfString: @" -" withString: @" " ];
@@ -116,15 +116,15 @@ -(NSString *)uuidForKey:(id<NSCopying>)key
116
116
if ( _uuidForKey == nil ){
117
117
_uuidForKey = [[NSMutableDictionary alloc ] init ];
118
118
}
119
-
119
+
120
120
NSString *uuidValue = [_uuidForKey objectForKey: key];
121
-
121
+
122
122
if ( uuidValue == nil ){
123
123
uuidValue = [self uuid ];
124
-
124
+
125
125
[_uuidForKey setObject: uuidValue forKey: key];
126
126
}
127
-
127
+
128
128
return uuidValue;
129
129
}
130
130
@@ -134,7 +134,7 @@ -(NSString *)uuidForSession
134
134
if ( _uuidForSession == nil ){
135
135
_uuidForSession = [self uuid ];
136
136
}
137
-
137
+
138
138
return _uuidForSession;
139
139
}
140
140
@@ -144,7 +144,7 @@ -(NSString *)uuidForInstallation
144
144
if ( _uuidForInstallation == nil ){
145
145
_uuidForInstallation = [self _getOrCreateValueForKey: _uuidForInstallationKey defaultValue: nil userDefaults: YES keychain: NO service: nil accessGroup: nil synchronizable: NO ];
146
146
}
147
-
147
+
148
148
return _uuidForInstallation;
149
149
}
150
150
@@ -154,7 +154,7 @@ -(NSString *)uuidForVendor
154
154
if ( _uuidForVendor == nil ){
155
155
_uuidForVendor = [[[[[UIDevice currentDevice ] identifierForVendor ] UUIDString ] lowercaseString ] stringByReplacingOccurrencesOfString: @" -" withString: @" " ];
156
156
}
157
-
157
+
158
158
return _uuidForVendor;
159
159
}
160
160
@@ -169,11 +169,11 @@ -(void)uuidForDevice_updateWithValue:(NSString *)value
169
169
-(NSString *)uuidForDevice
170
170
{
171
171
// also known as udid/uniqueDeviceIdentifier but this doesn't persists to system reset
172
-
172
+
173
173
if ( _uuidForDevice == nil ){
174
174
_uuidForDevice = [self _getOrCreateValueForKey: _uuidForDeviceKey defaultValue: nil userDefaults: YES keychain: YES service: nil accessGroup: nil synchronizable: NO ];
175
175
}
176
-
176
+
177
177
return _uuidForDevice;
178
178
}
179
179
@@ -184,23 +184,23 @@ -(NSString *)uuidForDeviceMigratingValue:(NSString *)value commitMigration:(BOOL
184
184
{
185
185
NSString *oldValue = [self uuidForDevice ];
186
186
NSString *newValue = [NSString stringWithString: value];
187
-
187
+
188
188
if ([oldValue isEqualToString: newValue])
189
189
{
190
190
return oldValue;
191
191
}
192
-
192
+
193
193
if (commitMigration)
194
194
{
195
195
[self uuidForDevice_updateWithValue: newValue];
196
-
196
+
197
197
NSMutableOrderedSet *uuidsOfUserDevicesSet = [[NSMutableOrderedSet alloc ] initWithArray: [self uuidsOfUserDevices ]];
198
198
[uuidsOfUserDevicesSet addObject: newValue];
199
199
[uuidsOfUserDevicesSet removeObject: oldValue];
200
-
200
+
201
201
[self uuidsOfUserDevices_updateWithValue: [uuidsOfUserDevicesSet array ]];
202
202
[self uuidsOfUserDevices_iCloudSync ];
203
-
203
+
204
204
return [self uuidForDevice ];
205
205
}
206
206
else {
@@ -209,7 +209,7 @@ -(NSString *)uuidForDeviceMigratingValue:(NSString *)value commitMigration:(BOOL
209
209
}
210
210
else {
211
211
[NSException raise :@" Invalid uuid to migrate" format: @" uuid value should be a string of 32 or 36 characters." ];
212
-
212
+
213
213
return nil ;
214
214
}
215
215
}
@@ -230,25 +230,25 @@ -(NSString *)uuidForDeviceMigratingValueForKey:(NSString *)key service:(NSString
230
230
-(NSString *)uuidForDeviceMigratingValueForKey : (NSString *)key service : (NSString *)service accessGroup : (NSString *)accessGroup commitMigration : (BOOL )commitMigration
231
231
{
232
232
NSString *uuidToMigrate = [self _getValueForKey: key userDefaults: YES keychain: YES service: service accessGroup: accessGroup];
233
-
233
+
234
234
return [self uuidForDeviceMigratingValue: uuidToMigrate commitMigration: commitMigration];
235
235
}
236
236
237
237
238
238
-(void )uuidsOfUserDevices_iCloudInit
239
239
{
240
240
_uuidsOfUserDevices_iCloudAvailable = NO ;
241
-
241
+
242
242
if (NSClassFromString (@" NSUbiquitousKeyValueStore" ))
243
243
{
244
244
NSUbiquitousKeyValueStore *iCloud = [NSUbiquitousKeyValueStore defaultStore ];
245
-
245
+
246
246
if (iCloud)
247
247
{
248
248
_uuidsOfUserDevices_iCloudAvailable = YES ;
249
-
249
+
250
250
[[NSNotificationCenter defaultCenter ] addObserver: self selector: @selector (uuidsOfUserDevices_iCloudChange: ) name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification object: nil ];
251
-
251
+
252
252
[self uuidsOfUserDevices_iCloudSync ];
253
253
}
254
254
else {
@@ -266,17 +266,17 @@ -(void)uuidsOfUserDevices_iCloudSync
266
266
if ( _uuidsOfUserDevices_iCloudAvailable )
267
267
{
268
268
NSUbiquitousKeyValueStore *iCloud = [NSUbiquitousKeyValueStore defaultStore ];
269
-
269
+
270
270
// if keychain contains more device identifiers than icloud, maybe that icloud has been empty, so re-write these identifiers to iCloud
271
271
for ( NSString *uuidOfUserDevice in [self uuidsOfUserDevices ] )
272
272
{
273
273
NSString *uuidOfUserDeviceAsKey = [NSString stringWithFormat: @" %@ _%@ " , _uuidForDeviceKey, uuidOfUserDevice];
274
-
274
+
275
275
if (![[iCloud stringForKey: uuidOfUserDeviceAsKey] isEqualToString: uuidOfUserDevice]){
276
276
[iCloud setString: uuidOfUserDevice forKey: uuidOfUserDeviceAsKey];
277
277
}
278
278
}
279
-
279
+
280
280
// toggle a boolean value to force notification on other devices, useful for debug
281
281
[iCloud setBool: ![iCloud boolForKey: _uuidsOfUserDevicesToggleKey] forKey: _uuidsOfUserDevicesToggleKey];
282
282
[iCloud synchronize ];
@@ -290,26 +290,26 @@ -(void)uuidsOfUserDevices_iCloudChange:(NSNotification *)notification
290
290
{
291
291
NSMutableOrderedSet *uuidsSet = [[NSMutableOrderedSet alloc ] initWithArray: [self uuidsOfUserDevices ]];
292
292
NSInteger uuidsCount = [uuidsSet count ];
293
-
293
+
294
294
NSUbiquitousKeyValueStore *iCloud = [NSUbiquitousKeyValueStore defaultStore ];
295
295
NSDictionary *iCloudDict = [iCloud dictionaryRepresentation ];
296
-
296
+
297
297
// NSLog(@"uuidsOfUserDevicesSync: %@", iCloudDict);
298
-
298
+
299
299
[iCloudDict enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
300
-
300
+
301
301
NSString *uuidKey = (NSString *)key;
302
-
302
+
303
303
if ([uuidKey rangeOfString: _uuidForDeviceKey].location == 0 )
304
304
{
305
305
if ([obj isKindOfClass: [NSString class ]])
306
306
{
307
307
NSString *uuidValue = (NSString *)obj;
308
-
308
+
309
309
if ([uuidKey rangeOfString: uuidValue].location != NSNotFound && [self uuidValueIsValid: uuidValue])
310
310
{
311
311
// NSLog(@"uuid: %@", uuidValue);
312
-
312
+
313
313
[uuidsSet addObject: uuidValue];
314
314
}
315
315
else {
@@ -318,11 +318,11 @@ -(void)uuidsOfUserDevices_iCloudChange:(NSNotification *)notification
318
318
}
319
319
}
320
320
}];
321
-
321
+
322
322
if ([uuidsSet count ] > uuidsCount)
323
323
{
324
324
[self uuidsOfUserDevices_updateWithValue: [uuidsSet array ]];
325
-
325
+
326
326
NSDictionary *userInfo = [NSDictionary dictionaryWithObject: [self uuidsOfUserDevices ] forKey: @" uuidsOfUserDevices" ];
327
327
[[NSNotificationCenter defaultCenter ] postNotificationName: FCUUIDsOfUserDevicesDidChangeNotification object: self userInfo: userInfo];
328
328
}
@@ -342,7 +342,7 @@ -(NSArray *)uuidsOfUserDevices
342
342
if ( _uuidsOfUserDevices == nil ){
343
343
_uuidsOfUserDevices = [self _getOrCreateValueForKey: _uuidsOfUserDevicesKey defaultValue: [self uuidForDevice ] userDefaults: YES keychain: YES service: nil accessGroup: nil synchronizable: YES ];
344
344
}
345
-
345
+
346
346
return [_uuidsOfUserDevices componentsSeparatedByString: @" |" ];
347
347
}
348
348
@@ -361,15 +361,15 @@ -(BOOL)uuidValueIsValid:(NSString *)uuidValue
361
361
{
362
362
NSString *uuidPattern = @" ^[0-9a-f]{32}|[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$" ;
363
363
NSRegularExpression *uuidRegExp = [NSRegularExpression regularExpressionWithPattern: uuidPattern options: NSRegularExpressionCaseInsensitive error: nil ];
364
-
364
+
365
365
NSRange uuidValueRange = NSMakeRange (0 , [uuidValue length ]);
366
366
NSRange uuidMatchRange = [uuidRegExp rangeOfFirstMatchInString: uuidValue options: 0 range: uuidValueRange];
367
367
NSString *uuidMatchValue;
368
-
368
+
369
369
if (!NSEqualRanges (uuidMatchRange, NSMakeRange (NSNotFound , 0 )))
370
370
{
371
371
uuidMatchValue = [uuidValue substringWithRange: uuidMatchRange];
372
-
372
+
373
373
if ([uuidMatchValue isEqualToString: uuidValue])
374
374
{
375
375
return YES ;
0 commit comments