-
-
Save Tron5000/7bb51318db1da86a3a78 to your computer and use it in GitHub Desktop.
| import Foundation | |
| // Compressing and decompressing a UUID to 22 characters via base64. | |
| // Works great as a Swift playground. These articles were helpful: | |
| // http://blog.codinghorror.com/equipping-our-ascii-armor/ | |
| // http://69.195.124.60/~jasondoh/2013/08/14/creating-a-short-guid-in-objective-c/ | |
| let identifier = NSUUID().uuidString | |
| let base64TailBuffer = "=" | |
| func compress(identifier: String) -> String? { | |
| guard let tempUuid = NSUUID(uuidString: identifier) else { | |
| return nil | |
| } | |
| var tempUuidBytes: UInt8 = 0 | |
| tempUuid.getBytes(&tempUuidBytes) | |
| let data = Data(bytes: &tempUuidBytes, count: 16) | |
| let base64 = data.base64EncodedString(options: NSData.Base64EncodingOptions()) | |
| return base64.replacingOccurrences(of: base64TailBuffer, with: "") | |
| } | |
| func rehydrate(shortenedIdentifier: String?) -> String? { | |
| // Expand an identifier out of a CBAdvertisementDataLocalNameKey or service characteristic. | |
| guard let shortenedIdentifier = shortenedIdentifier else { | |
| return nil | |
| } | |
| // Rehydrate the shortenedIdentifier | |
| let shortenedIdentifierWithDoubleEquals = shortenedIdentifier + base64TailBuffer + base64TailBuffer | |
| let data = Data(base64Encoded: shortenedIdentifierWithDoubleEquals) | |
| let uuidBytes = data?.withUnsafeBytes { $0.baseAddress?.assumingMemoryBound(to: UInt8.self) } | |
| let tempUuid = NSUUID(uuidBytes: uuidBytes) | |
| return tempUuid.uuidString | |
| } | |
| let testCompress = compress(identifier: identifier) | |
| let testRehydrate = rehydrate(shortenedIdentifier: testCompress) |
Glad this was helpful! I've updated the gist to accommodate the post-beta release of Swift.
Also, for anyone who is interested, I've written a blog post about this topic:
http://spinningtheweb.blogspot.com/2014/08/shortening-uuid-guid-in-swift.html
There's a memory corruption lurking here:
var tempUuidBytes: UInt8 = 0
tempUuid!.getUUIDBytes(&tempUuidBytes)
getUUIDBytes() writes 16 bytes, while &tempUuidBytes has allotted memory for just 1 byte.
@roop is right. This provided code crashes immediately for me in Xcode 7.1. Here's a modified version of the code that accepts nil and returns nil if something goes wrong (this met my use-case better).
func compressIdentifier(id: String?) -> String? {
let base64TailBuffer = "="
guard let identifier = id else {
return nil
}
guard let tempUuid = NSUUID(UUIDString: identifier) else {
return nil
}
var tempUuidBytes = [UInt8](count: 16, repeatedValue: 0)
tempUuid.getUUIDBytes(&tempUuidBytes)
let data = NSData(bytes: &tempUuidBytes, length: 16)
let base64 = data.base64EncodedStringWithOptions(NSDataBase64EncodingOptions())
return base64.stringByReplacingOccurrencesOfString(base64TailBuffer, withString: "", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil)
}
Good catch - thanks! I've updated the playground for Xcode 7.2.
I've updated again for Swift 3 and Xcode 8.
I've updated for Swift 5 and Xcode 10.2.1.
Is there a way to avoid special characters?
Thank you for this great piece of information! I used this to set my app UUID for a companion application for pebble smartwatch.