プッシュ通知を実装しています。 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を取得するにはどうすればよいですか?
これを使って :
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では、値のセマンティクスを備えたData
タイプが導入されています。 deviceToken
を文字列に変換するには、次のようにします。
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.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および最も簡単な方法が必要な場合
func extractTokenFromData(deviceToken:Data) -> String {
let token = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
return token.uppercased();
}
それは私のソリューションであり、私のアプリでうまく機能します:
NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken]
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
NSData
をNSString
でstringWithFormat
に変換しますDeviceTokenを16進バイト文字列に変換しても意味がないと思います。どうして?これをバックエンドに送信し、そこでAPNSにプッシュされるバイトに変換されます。したがって、NSDataのメソッド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])];
ワンラインソリューションはどうですか?
客観的C
NSString *token = [[data.description componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet]invertedSet]]componentsJoinedByString:@""];
Swift
let token = data.description.componentsSeparatedByCharactersInSet(NSCharacterSet.alphanumericCharacterSet().invertedSet).joinWithSeparator("")
一発ギャグ:
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つ の重複としてマークする方法がまだわからないので、答えをもう一度投稿しました)
高得点の%02.2hhx
の説明 answer :
%
:x
変換指定子を導入します。02
:変換された値の最小幅は2です。変換された値のフィールド幅よりもバイト数が少ない場合、左側に0
が埋め込まれます。.2
:x
変換指定子に表示される最小桁数を指定します。hh
:x
変換指定子が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
Swiftの場合:
var characterSet: NSCharacterSet = NSCharacterSet( charactersInString: "<>" )
var deviceTokenString: String = ( deviceToken.description as NSString )
.stringByTrimmingCharactersInSet( characterSet )
.stringByReplacingOccurrencesOfString( " ", withString: "" ) as String
println( deviceTokenString )
pdateAccumulatingResult を使用すると、ここにある他のさまざまなアプローチよりも効率的であるため、Data
バイトを文字列化するSwiftiestの方法を次に示します。
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.reduce(into: "") { $0 += String(format: "%.2x", $1) }
print(token)
}
山の上に私の答えを投げます。文字列解析の使用は避けてください。 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()
}
}
"%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)})
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)")
}
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
}
迅速:
let tokenString = deviceToken.description.stringByReplacingOccurrencesOfString("[ <>]", withString: "", options: .RegularExpressionSearch, range: nil)