I want to implement UUID v1 in my iOS App.
I know that it is composed of Mac Address and timestamp as described in
http://en.wikipedia.org/wiki/Universally_unique_identifier#Version_1_.28MAC_address.29
Is there any objective-c implementation for this V1, based on CFUUID functions ?
I already have the mac address and the timestamp.
The UUID v1 description at Wikipedia : "The original (version 1) generation scheme for UUIDs was to concatenate the UUID version with the MAC address of the computer that is generating the UUID, and with the number of 100-nanosecond intervals since the adoption of the Gregorian calendar in the West"
It is also specified at http://www.ietf.org/rfc/rfc4122.txt , but it seems that it will need time to implement it.
I have found this link : http://www.famkruithof.net/guid-uuid-timebased.html who have a simple explanation for the steps to create a v1 UUID. Is there any existing implementation, before I implement it by my self?
I thinks it is common behavior to use framework functions. And that is use CFUUID. For example:
+(NSString*)get {
NSString *deviceID = [[NSUserDefaults standardUserDefaults] objectForKey:#"DeviceID"];
if (!deviceID) {
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
deviceID = (NSString*)string;
[[NSUserDefaults standardUserDefaults] setValue:deviceID forKey:#"DeviceID"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
return deviceID;
}
Please try this one. It may be helpful to you
+(NSString*) Create_UDID
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
NSString* strString = [NSString stringWithFormat:#"%#", string];
NSString *strValue = [strString stringByReplacingOccurrencesOfString:#"-"withString:#""];
if (strValue == nil) {
strValue = #"";
}
return strValue;
}
Related
I wanna use SSKeychain to save CFUUID. But ever time I get CFUUID from SSKeychain is nil... I have read doc on github but still don't know what's wrong with it. Waiting for help~ please~~
NSString *retrieveuuid = [SSKeychain passwordForService:#"com.game.userinfo "account:#"uuid"];
if ( retrieveuuid == nil || [retrieveuuid isEqualToString:#""])
{
CFUUIDRef uuid = CFUUIDCreate(NULL);
assert(uuid != NULL);
CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid);
retrieveuuid = [NSString stringWithFormat:#"%#", uuidStr];
[SSKeychain setPassword: retrieveuuid
forService:#"com.game.userinfo"account:#"uuid"];
}
You have a trailing space character in "com.game.userinfo " on the first line (when looking up the UUID), but not in the last line when setting it. These strings should be identical.
I am getting following error but how to resolve it ?
Error is highlighted with green circle "Reference counted object is used after it is released"
Edited: I am using following method
+ (NSString *)GetUUID
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
NSString *str = (__bridge NSString *)string;
CFRelease(string);
return str;
}
Edited: Resolved by using vijay's following simple code
NSUUID *UUID = [NSUUID UUID];
NSString* stringUUID = [UUID UUIDString];
I hope, you are getting this error because of [DBManager GetUUID] method, where you would release the CFRelease(cfUuid).
To get the UUID, try this simplified API
+ (NSString *)GetUUID
{
NSUUID *UUID = [NSUUID UUID];
NSString* stringUUID = [UUID UUIDString];
return stringUUID;
}
After CFUUIDCreateString, you get a string you own. By using __bridge, you set str to the same string. So when you CFRelease(string) you do not own the memory backing str anymore...
To avoid this, either use a Cocoa method like #vijay says, or remove the CFRelease and use __bridge_transfer NSString* instead of __bridge. This tells the compiler you're transferring a CF object you own into the ARC world.
Per the documentation:
__bridge_transfer or CFBridgingRelease moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC. ARC is responsible
for relinquishing ownership of the object.
I can't find any official way to get a UUID string back out of a CBUUID. These UUIDs can be 2 or 16 bytes long.
The goal is to store CBUUIDs in a file somewhere as a string, and then resurrect with [CBUUID UUIDWithString:] etc. Here is what I have so far.
// returns a simple 4 byte string for 16bit uuids, 128 bit uuids are in standard 8-4-4-4-12 format
// the resulting string can be passed into [CBUUID UUIDWithString:]
+(NSString*)CBUUIDToString:(CBUUID*)cbuuid;
{
NSData* data = cbuuid.data;
if ([data length] == 2)
{
const unsigned char *tokenBytes = [data bytes];
return [NSString stringWithFormat:#"%02x%02x", tokenBytes[0], tokenBytes[1]];
}
else if ([data length] == 16)
{
NSUUID* nsuuid = [[NSUUID alloc] initWithUUIDBytes:[data bytes]];
return [nsuuid UUIDString];
}
return [cbuuid description]; // an error?
}
I rigged up the following category to do this for CBUUID:
#interface CBUUID (StringExtraction)
- (NSString *)representativeString;
#end
#implementation CBUUID (StringExtraction)
- (NSString *)representativeString;
{
NSData *data = [self data];
NSUInteger bytesToConvert = [data length];
const unsigned char *uuidBytes = [data bytes];
NSMutableString *outputString = [NSMutableString stringWithCapacity:16];
for (NSUInteger currentByteIndex = 0; currentByteIndex < bytesToConvert; currentByteIndex++)
{
switch (currentByteIndex)
{
case 3:
case 5:
case 7:
case 9:[outputString appendFormat:#"%02x-", uuidBytes[currentByteIndex]]; break;
default:[outputString appendFormat:#"%02x", uuidBytes[currentByteIndex]];
}
}
return outputString;
}
#end
For this input:
NSLog(#"UUID string: %#", [[CBUUID UUIDWithString:#"0bd51666-e7cb-469b-8e4d-2742f1ba77cc"] representativeString]);
NSLog(#"UUID string2: %#", [[CBUUID UUIDWithString:#"1800"] representativeString]);
it produces the following output:
UUID string: 0bd51666-e7cb-469b-8e4d-2742f1ba77cc
UUID string2: 1800
and preserves the appropriate hyphenation for the 16 byte UUIDs, while supporting the simple 2-byte UUIDs.
To all those saying that CBUUID is toll-free bridged with CFUUIDRef, it's not.
CBUUID * foo = [CBUUID UUIDWithString:CBUUIDCharacteristicExtendedPropertiesString];
CFStringRef fooBar = CFUUIDCreateString(NULL, (__bridge CFUUIDRef)foo);
if (![CBUUIDCharacteristicExtendedPropertiesString isEqualToString:(__bridge NSString *)fooBar])
NSLog(#"fubar!");
It's not crashing but you're getting garbage out. It's probably uniquely identifying garbage, but it can't be round-tripped.
PS: This didn't work as a comment because SO comments oddly don't allow code formatting.
iOS 7.1 (beta released yesterday, 11/18/13) introduced the following property on CBUUID:
#property(nonatomic, readonly) NSString *UUIDString
The UUID represented as a string. (read-only)
From CBUUID Class Reference.
It's also worth noting that for comparing a UUID string with a CBUUID, this works:
if ([cbuuidInQuestion isEqual:[CBUUID UUIDWithString:#"1234-5678-9012-1234"]]) {
// isEqual tests for "the same UUID"
// == tests for "the same CBUUID object"
}
I know it's been 7 month since it was asked and answered, but... CBUUID is “toll-free bridged” to CFUUID and the easiest way to convert is
//CBUUID* uuid = descr.UUID;
NSString* str = CFUUIDCreateString(nil, uuid);
Here is swift extension of Brad Larson's answer :
import CoreBluetooth
extension CBUUID {
func representativeString() -> String {
let data = self.data
let bytesToConvert = data.length
let uuidBytes = UnsafePointer<CUnsignedChar>(data.bytes)
var outputString = String()
for currentByteIndex in 0..<bytesToConvert {
switch currentByteIndex {
case 3,5,7,9:
outputString += String(format: "%02x-",uuidBytes[currentByteIndex])
default:
outputString += String(format: "%02x",uuidBytes[currentByteIndex])
}
}
return outputString
}
}
From iOS 7.1 UUIDString property is there but for specific iOS7, above extension is good option.
There is native method in objective C and Swift and it is quite straight forward method.
NSString *str = characteristic.UUID.UUIDstring;
Same thing with Swift language
Link to library->
https://developer.apple.com/documentation/corebluetooth/cbuuid/1518742-uuidstring?language=objc
Brad's answer does its work, but the solution could be simpler (though probably not more efficient) using NSUUID class:
// CBUUID+ToString.h
#import <CoreBluetooth/CoreBluetooth.h>
#interface CBUUID (ToString)
- (NSString *)toString;
#end
// CBUUID+ToString.m
#import "CBUUID+ToString.h"
#implementation CBUUID (ToString)
- (NSString *)toString {
if ([self respondsToSelector:#selector(UUIDString)]) {
return [self UUIDString]; // Available since iOS 7.1
} else {
return [[[NSUUID alloc] initWithUUIDBytes:[[self data] bytes]] UUIDString]; // iOS 6.0+
}
}
#end
The following Worked me without any error:
NSString *str = [[NSString alloc] initWithFormat:#"%#", CFUUIDCreateString(nil, peripheral.UUID) ];
How to get a UUID in objective c, like in Java UUID is used to generate unique random numbers which represents 128 bit value.
Try:
CFUUIDRef udid = CFUUIDCreate(NULL);
NSString *udidString = (NSString *) CFUUIDCreateString(NULL, udid);
UPDATE:
As of iOS 6, there is an easier way to generate UUID. And as usual, there are multiple ways to do it:
Create a UUID string:
NSString *uuid = [[NSUUID UUID] UUIDString];
Create a UUID:
[NSUUID UUID]; // which is the same as..
[[NSUUID] alloc] init];
Creates an object of type NSConcreteUUID and can be easily casted to NSString, and looks like this: BE5BA3D0-971C-4418-9ECF-E2D1ABCB66BE
NOTE from the Documentation:
Note: The NSUUID class is not toll-free bridged with CoreFoundation’s CFUUIDRef. Use UUID strings to convert between CFUUID and NSUUID, if needed. Two NSUUID objects are not guaranteed to be comparable by pointer value (as CFUUIDRef is); use isEqual: to compare two NSUUID instances.
Swift version of Raptor's answer:
let uuid = UUID().uuidString
+ (NSString *)uniqueFileName
{
CFUUIDRef theUniqueString = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUniqueString);
CFRelease(theUniqueString);
return [(NSString *)string autorelease];
}
-(NSString*) myUUID()
{
CFUUIDRef newUniqueID = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef newUniqueIDString = CFUUIDCreateString(kCFAllocatorDefault, newUniqueID);
NSString *guid = (__bridge NSString *)newUniqueIDString;
CFRelease(newUniqueIDString);
CFRelease(newUniqueID);
return([guid lowercaseString]);
}
you can use CFUUID for iOS 5 or lower version and NSUUID for iOS 6 and 7.
for making it more secure you can store your UUID in keychain
- (NSString*)generateGUID{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return [NSString stringWithFormat:#"%#", string];
}
For Swift 5.0, Use this,
let uuidRef = CFUUIDCreate(nil)
let uuidStringRef = CFUUIDCreateString(nil, uuidRef)
let uuid = uuidStringRef as String? ?? ""
I am looking at transitioning an app of mine from standard iOS Objective C to C# using MonoTouch.
In my Objective C code I am generating a unique identifier and saving it to NSUserDefaults to validate and check on subsequent logins. Here is the method that I am using for that:
- (NSString *) localUuid {
NSString * ident = [[NSUserDefaults standardUserDefaults] objectForKey:UUID];
if(!ident){
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStringRef = CFUUIDCreateString(NULL, uuidRef);
CFRelease(uuidRef);
ident = [NSString stringWithString:(__bridge_transfer NSString *)uuidStringRef];
[[NSUserDefaults standardUserDefaults] setObject:ident forKey:UUID];
[[NSUserDefaults standardUserDefaults] synchronize];
}
return ident;
}
I am having problems getting something similar to work in C# with MonoTouch though.
I haven't found a version of the CFUUID__ methods available with Mono.
Also, while there appears to be a NSUserDefaults.StandardUserDefaults.SetValueForKey method, there isn't a straightforward GetValueForKey method.
Does anyone more experienced with Monotouch know a better way to do this?
CFUUID is not bound because it's easier to use .NET System.Guid to achieve the same. E.g.
var uuid = Guid.NewGuid ();
string s = uuid.ToString (); // if a string is preferred
Also, while there appears to be a NSUserDefaults.StandardUserDefaults.SetValueForKey method, there isn't a straightforward GetValueForKey method.
There are safely type methods to do the same, e.g.:
NSUserDefaults settings = NSUserDefaults.StandardUserDefaults;
settings.SetString (s, "key");