Swift 3-장치 토큰이 이제 '32BYTES'로 구문 분석됩니다.


94

방금 Xcode 7에서 8 GM으로 업데이트했으며 Swift 3 호환성 문제 중에 장치 토큰이 작동을 멈췄다는 것을 알았습니다. 이제는 '32BYTES'만 읽습니다.

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
{
    print(deviceToken) // Prints '32BYTES'
    print(String(data: deviceToken , encoding: .utf8)) // Prints nil
}

업데이트 전에 NSData를 내 서버로 간단히 보낼 수 있었지만 이제 실제로 토큰을 구문 분석하는 데 어려움을 겪고 있습니다.

내가 여기서 무엇을 놓치고 있습니까?

편집 : 나는 NSData로 다시 변환하는 것을 테스트하고 예상되는 결과를보고 있습니다. 이제 새로운 데이터 유형에 대해 혼란스러워합니다.

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
{
    print(deviceToken) // Prints '32BYTES'
    print(String(data: deviceToken , encoding: .utf8)) // Prints nil

    let d = NSData(data: deviceToken)
    print(d) // Prints my device token
}

2
로 변경 NSData간단하게하면 인쇄 description의를 NSData. 당신은 여전히 ​​그것에서 문자열을 얻지 못합니다.
rmaddy

답변:


189
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
    print(token)
}

역 동작 (16 진수 문자열 -> 데이터)가 여기에 있습니다 : stackoverflow.com/a/46663290/5252428
한국 Gregorič

4
%02x괜찮아요.
jqgsninimo

1
@Rok 당신의 대답을 설명해 주시겠습니까? 토큰이 포맷 된 새로운 형식은 무엇입니까?
simo

@simo는 푸시 알림을 보낼 수 있도록 웹 서비스 / API에 전달할 수있는 데이터에서 16 진수 문자열로의 변환입니다.
한국 Gregorič

차이의 좋은 설명과 함께 좋은 포스트 %02.2hhx%02x nshipster.com/apns-device-tokens/#overturned-in-ios-13
한국 Gregorič

35

나는 같은 문제가 있었다. 이것이 내 해결책입니다.

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    var token = ""
    for i in 0..<deviceToken.count {
        token = token + String(format: "%02.2hhx", arguments: [deviceToken[i]])
    }
    print(token)
}

1
이것은를 NSData문자열로 인코딩하는 또 다른 방법 입니다. 내 대답에 base64 인코딩을 사용하는 것이 좋습니다. 이것은 base16 인코딩을 사용합니다.
rmaddy

@rmaddy 당신의 방식도 흥미롭지 만 코드에 대한 지침을 제공하면 더 도움이 될 것입니다 !!!
vivek agravat 2007

29

다음은 base-16으로 인코딩 된 16 진수 문자열을 가져 오는 Swift 3 확장입니다.

extension Data {
    var hexString: String {
        return map { String(format: "%02.2hhx", arguments: [$0]) }.joined()
    }
}

"% 02x"형식도 작동합니다. 나는 또한 무엇을 "HH"이해할 수없는
안드레이

1
@andrei "hh"는 입력을 문자로 처리하도록 문자열 포맷터에 지시합니다. 그러나 신속한에서, 데이터는 UINT8의 컬렉션은 당신이 그것을 필요가 없습니다입니다
wyu

27

장치 토큰은 문자열이 아니며 UTF-8로 인코딩 된 문자열이 아닙니다. 데이터입니다. 32 바이트의 불투명 한 데이터입니다.

불투명 한 데이터를 문자열로 변환하는 유일한 유효한 방법은 일반적으로 base64 인코딩을 통해 인코딩하는 것입니다.

Swift 3 / iOS 10에서는 간단히 Data base64EncodedString(options:)방법을 사용하십시오 .


여기서 차이점은 새로운 데이터 유형입니다. 방금 deviceToken을 NSData로 변환하려고 시도했으며 이제 이전과 마찬가지로 장치 토큰을 인쇄합니다. NSData없이 이것을 어떻게 처리 할 것인지에 대한 예가 있습니까? 이것은 엉망인 것처럼 느껴지지만 그들이 우리에게 기대하는 것보다 더 간단하기 때문입니다.
user1537360

3
나는 내가 말한 것을지지합니다. NSData또는 Data중요하지 않습니다. 데이터의 바이트는 문자열이 아니며 문자열이 아닙니다. 문서는 그것이 불투명 한 데이터 세트라고 분명히 명시합니다. 코드가 작동하는 데 사용되었다는 사실은 행운입니다. 그것은 항상 그것을 처리하는 잘못된 방법이었습니다. 데이터를 base64로 인코딩하여 데이터를 문자열로 변환하기 만하면됩니다. 그것은 지금과 이전에 적절한 해결책입니다.
rmaddy

Amazon SNS와 같은 서비스를 사용하는 경우 Base64 디코딩이 작동하지 않습니다. 데이터를 @satheeshwaran 과 같은 16 진수 문자로 변환하는 솔루션 은 SDK를 변경하기 전과 유사한 장치 토큰 문자열을 생성합니다.
알렉산더

@Alexander 누가 Base64 디코딩에 대해 말했습니까? 질문과 답변의 요점은 디코딩이 아닌 원시 데이터를 문자열로 인코딩 하는 것입니다. 이 작업을 수행하는 유일한 이유는 원시 데이터를 보는 것입니다. 특정 인코딩 체계는 관련이 없습니다. 다른 대답은 기본 16 인코딩을 사용하는 것입니다. Base 64 인코딩 사용에 대해 언급했습니다.
rmaddy

@rmaddy 내 의견에서 Base64 인코딩을 의미했습니다.
Alexander

15

이 시도:

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

   let token = String(data: deviceToken.base64EncodedData(), encoding: .utf8)?.trimmingCharacters(in: CharacterSet.whitespaces).trimmingCharacters(in: CharacterSet(charactersIn: "<>")) 
}

2
이제 다른 토큰을 반환하는 것 같습니다
ChikabuZ

8

이 시도

if #available(iOS 10.0, *) {
   let deviceTokenString = deviceToken.reduce("", {$0 + String(format: "%02X", $1)})
}

7

스위프트 3

가장 쉽고 쉬운 방법입니다.

deviceToken.base64EncodedString()

3
이것이 가장 쉽지만 토큰을 전달하는 경우 서버가 사용하는 것을주의하십시오. 많은 API는 Hex 인코딩 또는 Base-16을 기대합니다. 예를 들어 Django 푸시 알림입니다.
sww314

4

이것은 공식적인 답변으로 언급되지 않았지만 (댓글에서 보았습니다), 궁극적으로 토큰을 순서대로 되찾기 위해 제가 한 일입니다.

let tokenData = deviceToken as NSData
let token = tokenData.description

// remove any characters once you have token string if needed
token = token.replacingOccurrences(of: " ", with: "")
token = token.replacingOccurrences(of: "<", with: ""
token = token.replacingOccurrences(of: ">", with: "")

백엔드 API (Python)의 목적에 따라 이것은 "가장 깨끗한"솔루션이되었습니다. ¯ \ _ (ツ) _ / ¯
race_carr

1
iOS 10에서는 작동하지 않습니다. 설명은 이제 "32bytes"만 반환합니다.
edopelawi

@edopelawi 당신은 as NSData거기 에 넣는 것을 잊었습니다 . 데이터가 아닌 NSData로 입력하면 iOS 10에서도 올바른 값을 반환합니다
Jakub

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

    let token = deviceToken.map({ String(format: "%02.2hhx", $0)}).joined()
     print("TOKEN: " + token)


}

4
이 코드 블록이 질문에 답할 수 있지만 그 이유에 대해 약간의 설명을 제공하는 것이 가장 좋습니다.
Crispin

3

방금 했어요

let token = String(format:"%@",deviceToken as CVarArg).components(separatedBy: CharacterSet.alphanumerics.inverted).joined(separator: "")

결과는 다음과 같습니다.

let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()

0

적절한 형식으로 장치 토큰을 가져옵니다.

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) 
{
            var formattedToken = ""
            for i in 0..<deviceToken.count {
                formattedToken = formattedToken + String(format: "%02.2hhx", arguments: [deviceToken[i]])
            }
            print(formattedToken)
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.