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.