96
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {}

I want deviceToken to string

but:

let str = String.init(data: deviceToken, encoding: .utf8)

str is nil

swift 3.0

how can I let data to string ?

Registering for Push Notifications in Xcode 8/Swift 3.0? not working and the answer is a few months ago, I had tried it:

enter image description here

and print:

enter image description here

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
weijia.wang
  • 2,088
  • 2
  • 18
  • 32
  • 25
    Next time you ask someone to try out your code make sure it's not pasted as image.. – Desdenova Sep 21 '16 at 14:39
  • If someone comes across this when reading a file, check that the file is UTF8 encoded: `file -I /path/to/file.txt`. If not convert using iconv: `iconv -f UTF-16LE -t UTF-8 /path/to/file.txt > /path/to/utf8/file.txt` – Pulkit Goyal Apr 10 '17 at 08:02

12 Answers12

168

I came looking for the answer to the Swift 3 Data to String question and never got a good answer. After some fooling around I came up with this:

var testString = "This is a test string"
var somedata = testString.data(using: String.Encoding.utf8)
var backToString = String(data: somedata!, encoding: String.Encoding.utf8) as String!
4redwings
  • 1,796
  • 1
  • 9
  • 3
  • 4
    I had try you answer. It's worked in other func, but not working in `func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)`.I do not know why? – weijia.wang Jan 10 '17 at 13:35
  • the device token is not a utf8 string, it is raw binary – Hogdotmac Jul 31 '17 at 10:04
  • so what to do if it is raw binary? – Kingalione Sep 13 '17 at 12:02
  • String.Encoding.utf8.rawValue -- for anyone in the latest Swift – Stephen J Mar 30 '18 at 17:38
  • 1
    for decoding token using didRegisterForRemoteNotificationsWithDeviceToken see this: https://stackoverflow.com/questions/37956482/registering-for-push-notifications-in-xcode-8-swift-3-0 – pw2 Nov 05 '18 at 15:32
39

here is my data extension. add this and you can call data.ToString()

import Foundation

extension Data
{
    func toString() -> String?
    {
        return String(data: self, encoding: .utf8)
    }
}
luhuiya
  • 2,129
  • 21
  • 20
  • 1
    This is very bad coding - you should never force unwrap this since the encoding can always fail and this would crash the app. Instead return an optional string like the Apple API does for very good reasons. – Walter White Nov 21 '18 at 10:38
  • @WalterWhite yeah in the application i return optional string. but not update this answer, thanks for the comment – luhuiya Nov 26 '18 at 04:06
  • 1
    If you pass encoding as a parameter, maybe default it to .utf8 if you like, you can then use this for more than a single encoding type. – Micah Montoya May 06 '19 at 13:59
19
let str = deviceToken.map { String(format: "%02hhx", $0) }.joined()
Bugs
  • 4,491
  • 9
  • 32
  • 41
Hogdotmac
  • 282
  • 6
  • 7
7

I found the way to do it. You need to convert Data to NSData:

let characterSet = CharacterSet(charactersIn: "<>")
let nsdataStr = NSData.init(data: deviceToken)
let deviceStr = nsdataStr.description.trimmingCharacters(in: characterSet).replacingOccurrences(of: " ", with: "")
print(deviceStr)
Nookaraju
  • 1,668
  • 13
  • 24
weijia.wang
  • 2,088
  • 2
  • 18
  • 32
2

This is much easier in Swift 3 and later using reduce:

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

    DispatchQueue.global(qos: .background).async { 
        let url = URL(string: "https://example.com/myApp/apns.php")!

        var request = URLRequest(url: url)
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = try! JSONSerialization.data(withJSONObject: [
            "token" : token, 
            "ios" : UIDevice.current.systemVersion,
            "languages" : Locale.preferredLanguages.joined(separator: ", ")
            ])

        URLSession.shared.dataTask(with: request).resume()
    }
}
Gargoyle
  • 9,590
  • 16
  • 80
  • 145
2

Swift 4 version of 4redwings's answer:

let testString = "This is a test string"
let somedata = testString.data(using: String.Encoding.utf8)
let backToString = String(data: somedata!, encoding: String.Encoding.utf8)
Abhishek Jain
  • 4,557
  • 2
  • 32
  • 31
1

You can also use let data = String(decoding: myStr, as: UTF8.self) here is a resource about converting data to string

atalayasa
  • 3,310
  • 25
  • 42
1

for swift 5

let testString = "This is a test string"
let somedata = testString.data(using: String.Encoding.utf8)
let backToString = String(data: somedata!, encoding: String.Encoding.utf8) as String?
print("testString > \(testString)")
//testString > This is a test string
print("somedata > \(String(describing: somedata))")
//somedata > Optional(21 bytes)
print("backToString > \(String(describing: backToString))")
//backToString > Optional("This is a test string")
Zgpeace
  • 3,927
  • 33
  • 31
0

To extend on the answer of weijia.wang:

extension Data {
    func hexString() -> String {
        let nsdataStr = NSData.init(data: self)
        return nsdataStr.description.trimmingCharacters(in: CharacterSet(charactersIn: "<>")).replacingOccurrences(of: " ", with: "")
    }
}

use it with deviceToken.hexString()

Markus
  • 599
  • 1
  • 5
  • 18
0

According to the Apple doc below, device token can not be decoded. So, I think the best thing to do is just leave it be.

https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html

Security Architecture

A device token is an opaque NSData instance that contains a unique identifier assigned by Apple to a specific app on a specific device. Only APNs can decode and read the contents of a device token. Each app instance receives its unique device token when it registers with APNs, and must then forward the token to its provider, as described in Configuring Remote Notification Support. The provider must include the device token in each push notification request that targets the associated device; APNs uses the device token to ensure the notification is delivered only to the unique app-device combination for which it is intended.

Community
  • 1
  • 1
Kyle Bing
  • 179
  • 1
  • 18
0

If your data is base64 encoded.

if ( dataObj != nil ) {
    let encryptedDataText = dataObj!.base64EncodedString(options: NSData.Base64EncodingOptions())
    NSLog("Encrypted with pubkey: %@", encryptedDataText)
}
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
jeet.chanchawat
  • 5,842
  • 5
  • 38
  • 59
0
let urlString = baseURL + currency

    if let url = URL(string: urlString){
        let session = URLSession(configuration: .default)        
        let task = session.dataTask(with: url){ (data, reponse, error) in
            if error != nil{
                print(error)
                return
            }


            let dataString = String(data: data!, encoding: .utf8)
            print(dataString)

        }

        task.resume()

    }
Anjali Shah
  • 720
  • 7
  • 21