Как я могу преобразовать мой токен устройства (NSData) в строку NSString? - PullRequest
139 голосов
/ 21 февраля 2012

Я внедряю 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);
}

Первая строка кода печатает ноль.вторая печатает токен.Как я могу получить свой newDeviceToken как NSString?

Ответы [ 24 ]

200 голосов
/ 27 июля 2014

Если кто-то ищет способ сделать это в 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", $0) }.joined()
    print(token)
}
152 голосов
/ 21 февраля 2012

Кто-то помог мне с этим. Я просто передаю

- (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];
}
104 голосов
/ 07 мая 2013

Вы можете использовать это

- (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];
}
65 голосов
/ 21 февраля 2012

используйте это:

NSString * deviceTokenString = [[[[deviceToken description]
                         stringByReplacingOccurrencesOfString: @"<" withString: @""] 
                        stringByReplacingOccurrencesOfString: @">" withString: @""] 
                       stringByReplacingOccurrencesOfString: @" " withString: @""];

NSLog(@"The generated device token string is : %@",deviceTokenString);
37 голосов
/ 05 октября 2016

Для тех, кто хочет в Свифт 3 и самый простой способ

func extractTokenFromData(deviceToken:Data) -> String {
    let token = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
    return token.uppercased();
}
16 голосов
/ 10 января 2014

Это мое решение, и оно хорошо работает в моем приложении:

    NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken] 
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
  • преобразовать NSData в NSString с stringWithFormat
  • обрезать "<>"
  • убрать пробелы
8 голосов
/ 03 сентября 2015

Я думаю, что преобразование deviceToken в шестнадцатеричную байтовую строку не имеет смысла. Зачем? Вы отправите его на свой сервер, где он будет преобразован обратно в байты для отправки в APNS. Итак, используйте NSData метод base64EncodedStringWithOptions, отправьте его на сервер, а затем используйте обратные данные, декодированные base64 :) Это намного проще :)

NSString *tokenString = [tokenData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
4 голосов
/ 21 октября 2014

Это немного более короткое решение:

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])];
3 голосов
/ 07 октября 2015

Как насчет решения на одну линию?

Цель C

NSString *token = [[data.description componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet]invertedSet]]componentsJoinedByString:@""];

Swift

let token = data.description.componentsSeparatedByCharactersInSet(NSCharacterSet.alphanumericCharacterSet().invertedSet).joinWithSeparator("")
3 голосов
/ 01 марта 2016

Функциональная версия Swift

Один вкладыш:

let hexString = UnsafeBufferPointer<UInt8>(start: UnsafePointer(data.bytes),
count: data.length).map { String(format: "%02x", $0) }.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, $0)
        }
        return bytesAsHexStrings.joinWithSeparator("")
    }
}

В качестве альтернативы, используйте reduce("", combine: +) вместо joinWithSeparator(""), чтобы ваши коллеги воспринимали его как функционального мастера.


Редактировать: Я изменил String ($ 0, radix: 16) на String (формат: "% 02x", $ 0), потому что однозначные числа должны иметь нулевой отступ

(я пока не знаю, как пометить вопрос как дубликат этого другого , поэтому я просто опубликовал свой ответ снова)

...