web-dev-qa-db-ja.com

デバイストークン(NSData)をNSStringに変換するにはどうすればよいですか?

プッシュ通知を実装しています。 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を出力します。 2番目はトークンを出力します。 NSDeviceとしてnewDeviceTokenを取得するにはどうすればよいですか?

142
Sheehan Alam

これを使って :

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

NSLog(@"The generated device token string is : %@",deviceTokenString);
62
kulss

誰かが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)
}
204
Sascha

誰かがこれを手伝ってくれました。

- (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];
}
152
Shubhank

これを使用できます

- (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];
}
104
Vlad Polyanskiy

Swiftおよび最も簡単な方法が必要な場合

func extractTokenFromData(deviceToken:Data) -> String {
    let token = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
    return token.uppercased();
}
39
Anand

それは私のソリューションであり、私のアプリでうまく機能します:

    NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken] 
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
  • NSDataNSStringstringWithFormatに変換します
  • 「<>」を削除します
  • スペースを削除する
17
Zeb

DeviceTokenを16進バイト文字列に変換しても意味がないと思います。どうして?これをバックエンドに送信し、そこでAPNSにプッシュされるバイトに変換されます。したがって、NSDataのメソッドbase64EncodedStringWithOptionsを使用し、サーバーにプッシュしてから、逆base64decodedデータを使用します:)これは非常に簡単です:)

NSString *tokenString = [tokenData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
8
Oleg Shanyuk

これは少し短いソリューションです:

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])];
4
k06a

ワンラインソリューションはどうですか?

客観的C

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

Swift

let token = data.description.componentsSeparatedByCharactersInSet(NSCharacterSet.alphanumericCharacterSet().invertedSet).joinWithSeparator("")
3

機能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("")を使用して、ピアから機能マスターとして認識されます。


編集:文字列($ 0、基数:16)を文字列(形式:「%02x」、$ 0)に変更しました。1桁の数字にパディングゼロを含める必要があるためです

(質問を このもう1つ の重複としてマークする方法がまだわからないので、答えをもう一度投稿しました)

3
NiñoScript

高得点の%02.2hhxの説明 answer

  • %x変換指定子を導入します。
  • 02:変換された値の最小幅は2です。変換された値のフィールド幅よりもバイト数が少ない場合、左側に0が埋め込まれます。
  • .2x変換指定子に表示される最小桁数を指定します。
  • hhx変換指定子がsigned charまたはunsigned char引数に適用されることを指定します(引数は整数プロモーションに従って昇格されますが、その値はsigned charまたはunsigned charに変換されます。印刷する前に)。
  • x:符号なし引数は、スタイル「dddd」の符号なし16進形式に変換されます。文字「abcdef」が使用されます。精度は、表示される最小桁数を指定します。変換される値をより少ない桁数で表すことができる場合、先行ゼロで拡張されます。デフォルトの精度は1です。明示的な精度ゼロでゼロを変換した結果は、文字になりません。

詳細については、 IEEE printf specification を参照してください。


上記の説明に基づいて、%02.2hhx%02xまたは%.2xに変更することをお勧めします。

Swift 5の場合、次の方法がすべて実行可能です。

deviceToken.map({String(format: "%02x", $0)}).joined()
deviceToken.map({String(format: "%.2x", $0)}).joined()
deviceToken.reduce("", {$0 + String(format: "%02x", $1)})
deviceToken.reduce("", {$0 + String(format: "%.2x", $1)})

テストは次のとおりです。

let deviceToken = (0..<32).reduce(Data(), {$0 + [$1]})
print(deviceToken.reduce("", {$0 + String(format: "%.2x", $1)}))
// Print content:
// 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
2
jqgsninimo

Swiftの場合:

var characterSet: NSCharacterSet = NSCharacterSet( charactersInString: "<>" )
    var deviceTokenString: String = ( deviceToken.description as NSString )
    .stringByTrimmingCharactersInSet( characterSet )
    .stringByReplacingOccurrencesOfString( " ", withString: "" ) as String

println( deviceTokenString )
1
Adarsh G J

pdateAccumulatingResult を使用すると、ここにある他のさまざまなアプローチよりも効率的であるため、Dataバイトを文字列化するSwiftiestの方法を次に示します。

func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.reduce(into: "") { $0 += String(format: "%.2x", $1) }
    print(token)
}
1
Alex Curylo

山の上に私の答えを投げます。文字列解析の使用は避けてください。 NSData.descriptionが常にそのように機能することは、ドキュメントによって保証されていません。

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", $0) }
        return hexBytes.joined()
    }
}
1
swift taylor

"%02.2hhx""%02x"の形式で2つの異なるメソッドをテストしようとしました

    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", $0) }.joined()
        i += 1
    }
    let time2 = NSDate.timeIntervalSinceReferenceDate
    let delta = time2-time
    print(delta)

    let time3 = NSDate.timeIntervalSinceReferenceDate
    while j < e {
        _ =  deviceToken.reduce("", {$0 + String(format: "%02x", $1)})
        j += 1
    }
    let time4 = NSDate.timeIntervalSinceReferenceDate
    let delta2 = time4-time3
    print(delta2)

その結果、最高速は"%02x"であり、平均では2.0であり、縮小版では2.6です。

deviceToken.reduce("", {$0 + String(format: "%02x", $1)})
1
Nicolas Manzini

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)")

    }
0
Vinod Joshi

Xamarin.iOSで行う方法は次のとおりです。

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
    var tokenStringBase64 = deviceToken.GetBase64EncodedString(NSDataBase64EncodingOptions.None);
    //now you can store it for later use in local storage
}
0
HeisenBerg

迅速:

let tokenString = deviceToken.description.stringByReplacingOccurrencesOfString("[ <>]", withString: "", options: .RegularExpressionSearch, range: nil)
0
Tony