可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am implementing push notifications. I'd like to save my APNS Token as a String.
- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)newDeviceToken
{
NSString *tokenString = [NSString stringWithUTF8String:[newDeviceToken bytes]]; //[[NSString alloc]initWithData:newDeviceToken encoding:NSUTF8StringEncoding];
NSLog(@"%@", tokenString);
NSLog(@"%@", newDeviceToken);
}
The first line of code prints null. the second prints the token. How can I get my newDeviceToken as an NSString?
回答1:
use this :
NSString * deviceTokenString = [[[[deviceToken description]
stringByReplacingOccurrencesOfString: @"<" withString: @""]
stringByReplacingOccurrencesOfString: @">" withString: @""]
stringByReplacingOccurrencesOfString: @" " withString: @""];
NSLog(@"The generated device token string is : %@",deviceTokenString);
回答2:
If anyone is looking for a way to do this in 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)")
}
Edit: For Swift 3
Swift 3 introduces the Data
type, with value semantics. To convert the deviceToken
to a String, you can do as follows:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
print(token)
}
回答3:
Someone Helped me with this.I am just passing along
- (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];
}
回答4:
You could use this
- (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];
}
回答5:
For those who want in Swift 3 and most easier method
func extractTokenFromData(deviceToken:Data) -> String {
let token = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
return token.uppercased();
}
回答6:
It's my solution and It works well in my app:
NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken]
stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""];
- convert
NSData
to NSString
with stringWithFormat
- trim the "<>"
- remove the spaces
回答7:
I think converting deviceToken to hex byte string has no sense. Why? You will send it to your backend, where it will be transformed back to bytes to be pushed to APNS. So, use NSData's method base64EncodedStringWithOptions
, push it to server, and then use reverse base64decoded data :) That is so much easier :)
NSString *tokenString = [tokenData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
回答8:
This is a little bit shorter solution:
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])];
回答9:
What about one line solution?
Objective C
NSString *token = [[data.description componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet]invertedSet]]componentsJoinedByString:@""];
Swift
let token = data.description.componentsSeparatedByCharactersInSet(NSCharacterSet.alphanumericCharacterSet().invertedSet).joinWithSeparator("")
回答10:
Functional Swift version
One liner:
let hexString = UnsafeBufferPointer<UInt8>(start: UnsafePointer(data.bytes),
count: data.length).map { String(format: "%02x", $0) }.joinWithSeparator("")
Here's in a reusable and self documenting extension form:
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("")
}
}
Alternatively, use reduce("", combine: +)
instead of joinWithSeparator("")
to be seen as a functional master by your peers.
Edit: I changed String($0, radix: 16) to String(format: "%02x", $0), because one digit numbers needed to having a padding zero
(I don't know yet how to mark a question as a duplicate of this other one, so I just posted my answer again)
回答11:
For Swift :
var characterSet: NSCharacterSet = NSCharacterSet( charactersInString: "<>" )
var deviceTokenString: String = ( deviceToken.description as NSString )
.stringByTrimmingCharactersInSet( characterSet )
.stringByReplacingOccurrencesOfString( " ", withString: "" ) as String
println( deviceTokenString )
回答12:
Throwing my answer on the pile. Avoid using string parsing; It's not guaranteed by the docs that NSData.description will always work that way.
Swift 3 Implementation:
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()
}
}
回答13:
Swift:
let tokenString = deviceToken.description.stringByReplacingOccurrencesOfString("[ <>]", withString: "", options: .RegularExpressionSearch, range: nil)
回答14:
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)")
}
回答15:
I've tried to test two different methods with format "%02.2hhx"
and "%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", $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)
and the result is that the fastest is "%02x"
at average 2.0 vs 2.6 for the reduced version:
deviceToken.reduce("", {$0 + String(format: "%02x", $1)})
回答16:
-(NSString *)deviceTokenWithData:(NSData *)data
{
NSString *deviceToken = [[data description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
deviceToken = [deviceToken stringByReplacingOccurrencesOfString:@" " withString:@""];
return deviceToken;
}
回答17:
NSString *tokenString = [[newDeviceToken description] stringByReplacingOccurrencesOfString:@"[<> ]" withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, [[newDeviceToken description] length])];
回答18:
Swift 3:
If any one is looking for a way to get device token in Swift 3. Use the below modified snippet.
let characterSet: CharacterSet = CharacterSet( charactersIn: "<>" )
let deviceTokenString: String = (deviceToken.description as NSString)
.trimmingCharacters(in: characterSet as CharacterSet)
.replacingOccurrences(of: " ", with: "")
.uppercased()
print(deviceTokenString)
回答19:
Use excellent category!
// .h file
@interface NSData (DeviceToken)
- (NSString *)stringDeviceToken;
@end
// .m file
#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.m
#import "NSData+DeviceToken.h"
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSString *token = deviceToken.stringDeviceToken;
}
Works fine!
回答20:
var token: String = ""
for i in 0..<deviceToken.count {
token += String(format: "%02.2hhx", deviceToken[i] as CVarArg)
}
print(token)
回答21:
Try this one unless the data is null-terminated.
NSString* newStr = [[NSString alloc] initWithData:newDeviceToken
encoding:NSUTF8StringEncoding];
回答22:
NSString *tokenstring = [[NSString alloc] initWithData:token encoding:NSUTF8StringEncoding];