Swift 3 - cihaz belirteçleri artık '32BYTES' olarak ayrıştırılıyor


94

Xcode 7'den 8 GM'ye yeni güncelledim ve Swift 3 uyumluluk sorunları arasında cihaz tokenlerimin çalışmayı durdurduğunu fark ettim. Artık sadece '32BYTES' okuyorlar.

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

Güncellemeden önce NSData'yı sunucuma gönderebiliyordum, ancak şimdi jetonu gerçekten ayrıştırmakta zorlanıyorum.

Burada neyi özlüyorum?

Düzenleme: Sadece NSData'ya geri dönüştürmeyi test ediyorum ve beklenen sonuçları görüyorum. Şimdi yeni Veri türü konusunda kafam karıştı.

    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
İçin değiştirme NSDatabasitçe yazdırır descriptionarasında NSData. Hala bundan bir ip alamıyorsun.
rmaddy

Yanıtlar:


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

Ters işlem (onaltılık Dize -> Veri) burada mevcuttur: stackoverflow.com/a/46663290/5252428
Rok Gregorič

4
%02xtamamdır.
jqgsninimo

1
@Rok cevabınızı açıklar mısınız? jetonun biçimlendirildiği yeni biçim nedir?
simo

@simo, Verilerden, push bildirimleri gönderebilmek için bir web hizmetine / API'ye iletebileceğiniz onaltılık dizeye bir dönüşümdür.
Rok Gregorič


35

Ben de aynı sorunu yaşadım. Bu benim çözümüm:

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
Bu, NSDatadizeyi kodlamak için alternatif bir yaklaşımdır . Cevabımda base64 kodlamasını kullanmayı önerdim. Bu, base16 kodlamasını kullanır.
rmaddy

@rmaddy senin yolun da ilginç ama bize kodla ilgili biraz rehberlik verirsen daha faydalı olur !!!
vivek agravat

29

İşte 16 tabanlı kodlanmış bir onaltılık dizge almak için Swift 3 uzantım:

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

"% 02x" biçiminin de çalıştığını fark ettim. Ayrıca "hh" nin ne yaptığını da anlayamıyorum
andrei

1
@andrei "hh", dize biçimlendiriciye girişi bir karakter olarak ele almasını söyler. Bununla birlikte, hızlı bir şekilde, Data bir UInt8 koleksiyonudur, bu nedenle buna ihtiyacınız yoktur
wyu

27

Aygıt simgesi hiçbir zaman bir dizge ve kesinlikle UTF-8 kodlu bir dizge olmamıştır. Veriler. 32 baytlık opak veri.

Opak verileri bir dizeye dönüştürmenin tek geçerli yolu, onu kodlamaktır - genellikle bir base64 kodlamasıyla.

Swift 3 / iOS 10'da Data base64EncodedString(options:)yöntemi kullanın .


Buradaki fark, yeni Veri türü. DeviceToken'ı NSData'ya dönüştürmeyi denedim ve şimdi daha önce olduğu gibi cihaz simgemi yazdırıyor. NSData olmadan bununla nasıl başa çıkacağınıza dair bir örneğiniz var mı? Çünkü bu hile gibi geliyor, ama aynı zamanda bizden yapmamızı beklediklerinden daha basit.
user1537360

3
Söylediğim şeyin arkasında duruyorum. NSDataya da Dataönemli değil. Verilerin baytları bir dizge değildir ve asla olmamıştır. Belgeler, bunun opak bir veri kümesi olduğunu açıkça belirtir. Kodunuzun işe yaraması şanstır. Bununla başa çıkmanın her zaman yanlış yolu buydu. Verileri base64 kodlayarak basitçe bir dizeye dönüştürün. Şimdi ve öncesinde bu doğru çözüm.
rmaddy

Amazon SNS gibi bir hizmet kullanıyorsanız Base64 kod çözme çalışmaz. @Satheeshwaran 's gibi verileri onaltılık karakterlere dönüştüren çözümler , SDK'da yapılan değişikliklerden öncekilere benzeyen cihaz belirteci dizeleri üretir.
Alexander

@Alexander Base64 kod çözme hakkında kim bir şey söyledi? Sorunun ve yanıtların tüm amacı , ham verileri bir dizge olarak çözmek değil kodlamaktır . Bunlardan herhangi birini yapmanın tek nedeni ham verileri görüntülemektir. Spesifik kodlama şeması konu dışıdır. Diğer cevap 16 tabanlı kodlamayı kullanıyor. Temel 64 kodlamasını kullanmaktan bahsetmiştim.
rmaddy

@rmaddy Yorumumda Base64 kodlamasını kastettim, özür dilerim.
Alexander

15

Bunu dene:

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

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

2
Görünüşe göre şimdi farklı bir token döndürüyor
ChikabuZ

8

bunu dene

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

7

Hızlı 3

En iyi ve en kolay yol.

deviceToken.base64EncodedString()

3
Bu en kolayıdır, ancak jetonu teslim ediyorsanız sunucunuzun ne kullandığına dikkat edin. Birçok API Hex kodlu veya Base-16 ile bekler. Örneğin, Django Push Bildirimleri.
sww314

4

Bu, resmi bir cevap olarak belirtilmedi (bir yorumda gördüm), ancak sonuçta jetonumu geri almak için yaptığım şey buydu.

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: "")

arka uç API'mizin (Python) amaçları doğrultusunda, bu "en temiz" çözüm oldu ¯ \ _ (ツ) _ / ¯
race_carr

1
Bu, iOS 10'da çalışmaz. Açıklama artık yalnızca "32 bayt" döndürüyor.
edopelawi

@edopelawi as NSDataoraya koymayı unuttunuz . NSData not Data olarak koyduğunuzda, iOS 10'da bile doğru değeri döndürür
Jakub

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

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


}

4
Bu kod bloğu soruyu yanıtlasa da, bunu neden yaptığına dair küçük bir açıklama yapsanız en iyisi olur.
Crispin

3

Bunu şimdi yaptım

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

aynı sonucu verdi,

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

0

Uygun formatta cihaz jetonu alın.

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)
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.