Как я могу преобразовать мой токен устройства (NSData) в NSString?
я внедряю push-уведомления. Я хотел бы сохранить свой маркер APNS в виде строки.
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)newDeviceToken
{
NSString *tokenString = [NSString stringWithUTF8String:[newDeviceToken bytes]]; //[[NSString alloc]initWithData:newDeviceToken encoding:NSUTF8StringEncoding];
NSLog(@"%@", tokenString);
NSLog(@"%@", newDeviceToken);
}
первая строка кода выводит null. второй печатает маркер. Как я могу получить мой newDeviceToken в качестве NSString?
22 ответа:
используйте этот :
NSString * deviceTokenString = [[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""] stringByReplacingOccurrencesOfString: @">" withString: @""] stringByReplacingOccurrencesOfString: @" " withString: @""]; NSLog(@"The generated device token string is : %@",deviceTokenString);
если кто-то ищет способ сделать это в Swift:
func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) { let tokenChars = UnsafePointer<CChar>(deviceToken.bytes) var tokenString = "" for i in 0..<deviceToken.length { tokenString += String(format: "%02.2hhx", arguments: [tokenChars[i]]) } print("tokenString: \(tokenString)") }
Изменить: Для Swift 3
Swift 3 представляет
Data
тип, с семантикой значений. Чтобы преобразоватьdeviceToken
к строке, вы можете сделать следующее:func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let token = deviceToken.map { String(format: "%02.2hhx", ) }.joined() print(token) }
кто-то помог мне с этим.Я просто прохожу мимо
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken { const unsigned *tokenBytes = [deviceToken bytes]; NSString *hexToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x", ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]), ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]), ntohl(tokenBytes[6]), ntohl(tokenBytes[7])]; [[MyModel sharedModel] setApnsToken:hexToken]; }
вы могли бы использовать это
- (NSString *)stringWithDeviceToken:(NSData *)deviceToken { const char *data = [deviceToken bytes]; NSMutableString *token = [NSMutableString string]; for (NSUInteger i = 0; i < [deviceToken length]; i++) { [token appendFormat:@"%02.2hhX", data[i]]; } return [token copy]; }
для тех, кто хочет в Swift 3 и самый простой метод
func extractTokenFromData(deviceToken:Data) -> String { let token = deviceToken.reduce("", { + String(format: "%02X", )}) return token.uppercased(); }
это мое решение, и оно хорошо работает в моем приложении:
NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
- преобразование
NSData
toNSString
СstringWithFormat
- обрезать ""
- удалите пробелы
Я думаю, что преобразование deviceToken в шестнадцатеричную байтовую строку не имеет смысла. Зачем? Вы отправите его на свой бэкэнд, где он будет преобразован обратно в байты для отправки в APNS. Итак, используйте NSData ' s метод
base64EncodedStringWithOptions
, нажмите его на сервер, а затем используйте обратные base64decoded данные :) это намного проще :)NSString *tokenString = [tokenData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
это немного более короткое решение:
NSData *token = // ... const uint64_t *tokenBytes = token.bytes; NSString *hex = [NSString stringWithFormat:@"%016llx%016llx%016llx%016llx", ntohll(tokenBytes[0]), ntohll(tokenBytes[1]), ntohll(tokenBytes[2]), ntohll(tokenBytes[3])];
функциональная версия Swift
один лайнер:
let hexString = UnsafeBufferPointer<UInt8>(start: UnsafePointer(data.bytes), count: data.length).map { String(format: "%02x", ) }.joinWithSeparator("")
вот в многоразовой и самодокументированной форме расширения:
extension NSData { func base16EncodedString(uppercase uppercase: Bool = false) -> String { let buffer = UnsafeBufferPointer<UInt8>(start: UnsafePointer(self.bytes), count: self.length) let hexFormat = uppercase ? "X" : "x" let formatString = "%02\(hexFormat)" let bytesAsHexStrings = buffer.map { String(format: formatString, ) } return bytesAsHexStrings.joinWithSeparator("") } }
в качестве альтернативы, используйте
reduce("", combine: +)
вместоjoinWithSeparator("")
чтобы ваши сверстники видели вас в качестве функционального мастера.
Edit: я изменил строку ($0, radix: 16) на строку(формат: "%02x", $0), потому что одноразрядные числа необходимы для заполнения нуля
(Я еще не знаю, как пометить вопрос как дубликат этот, так что я просто отправил свой ответ снова)
кто-нибудь решение?
С
NSString *token = [[data.description componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet]invertedSet]]componentsJoinedByString:@""];
Свифт
let token = data.description.componentsSeparatedByCharactersInSet(NSCharacterSet.alphanumericCharacterSet().invertedSet).joinWithSeparator("")
Для Swift :
var characterSet: NSCharacterSet = NSCharacterSet( charactersInString: "<>" ) var deviceTokenString: String = ( deviceToken.description as NSString ) .stringByTrimmingCharactersInSet( characterSet ) .stringByReplacingOccurrencesOfString( " ", withString: "" ) as String println( deviceTokenString )
бросая мой ответ на кучу. Избегайте использования синтаксического анализа строк; это не гарантируется документами, которые NSData.описание всегда будет работать таким образом.
Swift 3 Реализация:
extension Data { func hexString() -> String { var bytesPointer: UnsafeBufferPointer<UInt8> = UnsafeBufferPointer(start: nil, count: 0) self.withUnsafeBytes { (bytes) in bytesPointer = UnsafeBufferPointer<UInt8>(start: UnsafePointer(bytes), count:self.count) } let hexBytes = bytesPointer.map { return String(format: "%02hhx", ) } return hexBytes.joined() } }
Swift:
let tokenString = deviceToken.description.stringByReplacingOccurrencesOfString("[ <>]", withString: "", options: .RegularExpressionSearch, range: nil)
Swift
// make sure that we have token for the devie on the App func application(application: UIApplication , didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) { var tokenStr = deviceToken.description tokenStr = tokenStr.stringByReplacingOccurrencesOfString("<", withString: "", options: [], range: nil) tokenStr = tokenStr.stringByReplacingOccurrencesOfString(">", withString: "", options: [], range: nil) tokenStr = tokenStr.stringByReplacingOccurrencesOfString(" ", withString: "", options: [], range: nil) print("my token is: \(tokenStr)") }
Я пытался протестировать два разных метода с форматом
"%02.2hhx"
и"%02x"
var i :Int = 0 var j: Int = 0 let e: Int = Int(1e4) let time = NSDate.timeIntervalSinceReferenceDate while i < e { _ = deviceToken.map { String(format: "%02x", ) }.joined() i += 1 } let time2 = NSDate.timeIntervalSinceReferenceDate let delta = time2-time print(delta) let time3 = NSDate.timeIntervalSinceReferenceDate while j < e { _ = deviceToken.reduce("", { + String(format: "%02x", )}) j += 1 } let time4 = NSDate.timeIntervalSinceReferenceDate let delta2 = time4-time3 print(delta2)
и в результате получается, что самый быстрый
"%02x"
в среднем 2.0 против 2.6 на сокращенную версию:deviceToken.reduce("", { + String(format: "%02x", )})
-(NSString *)deviceTokenWithData:(NSData *)data { NSString *deviceToken = [[data description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; deviceToken = [deviceToken stringByReplacingOccurrencesOfString:@" " withString:@""]; return deviceToken; }
NSString *tokenString = [[newDeviceToken description] stringByReplacingOccurrencesOfString:@"[<> ]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [[newDeviceToken description] length])];
Swift 3:
Если кто-то ищет способ получить маркер устройства в Swift 3. Используйте приведенный ниже измененный фрагмент кода.
let characterSet: CharacterSet = CharacterSet( charactersIn: "<>" ) let deviceTokenString: String = (deviceToken.description as NSString) .trimmingCharacters(in: characterSet as CharacterSet) .replacingOccurrences(of: " ", with: "") .uppercased() print(deviceTokenString)
используйте отличную категории!
// .файл H
@interface NSData (DeviceToken) - (NSString *)stringDeviceToken; @end
// .файл м
#import "NSData+DeviceToken.h" @implementation NSData (DeviceToken) - (NSString *)stringDeviceToken { const unsigned *deviceTokenBytes = [deviceToken bytes]; NSString *deviceToken = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x", ntohl(deviceTokenBytes[0]), ntohl(deviceTokenBytes[1]), ntohl(deviceTokenBytes[2]), ntohl(deviceTokenBytes[3]), ntohl(deviceTokenBytes[4]), ntohl(deviceTokenBytes[5]), ntohl(deviceTokenBytes[6]), ntohl(deviceTokenBytes[7])]; return deviceToken; }
@end
/ / AppDelegate.м
#import "NSData+DeviceToken.h" - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSString *token = deviceToken.stringDeviceToken; }
работает отлично!
var token: String = "" for i in 0..<deviceToken.count { token += String(format: "%02.2hhx", deviceToken[i] as CVarArg) } print(token)