2017-06-23 4 views
0

Après avoir envoyé une requête HTTP à Swift, j'obtiens un champ dans la réponse appelé textEncodingName.Comment puis-je convertir une chaîne, telle que "iso-8859-1", en sa contrepartie String.Encoding?

Je veux convertir l'objet data que j'ai également reçu en une chaîne contenant son contenu, et pour ce faire, j'utilise String(data: data!, encoding: .utf8). Cela fonctionne la plupart du temps, car la plupart des sites Web sont codés en UTF-8. Mais avec, par exemple, https://www.google.co.uk, le response.textEncodingName == "iso-8859-1". Je suppose que d'autres sites utiliseraient des encodages encore plus obscurs, alors ma question est la suivante: comment puis-je trouver le bon codage pour convertir mon objet data en la chaîne correcte.

Répondre

2

Je trouve à quelques pas qui vous mènera du textEncodingName à la String.Encoding valeur correspondante:

let estr = "iso-8859-1" 
let cfe = CFStringConvertIANACharSetNameToEncoding(estr as CFString) 
let se = CFStringConvertEncodingToNSStringEncoding(cfe) 
let encoding = String.Encoding(rawValue: se) 

Ceci est en grande partie basée sur la documentation URLResponse.textEncodingName:

Vous pouvez convertissez cette chaîne en une valeur CFStringEncoding en appelant CFStringConvertIANACharSetNameToEncoding (:). Vous pouvez ensuite convertir cette valeur à une valeur NSStringEncoding en appelant CFStringConvertEncodingToNSStringEncoding ( :).

est ici une mise à jour qui vérifie si la chaîne de codage de texte d'origine est valide ou non:

let estr = "XXX" 
let cfe = CFStringConvertIANACharSetNameToEncoding(estr as CFString) 
if cfe != kCFStringEncodingInvalidId { 
    let se = CFStringConvertEncodingToNSStringEncoding(cfe) 
    let sse = String.Encoding(rawValue: se) 
    print("sse = \(sse)") 
} else { 
    print("Invalid") 
} 
+0

Avez-vous une idée de ce qui se produire si le codage n'a pas été reconnu? – Zac

+0

@Zac Voir ma mise à jour pour vérifier si l'encodage est valide ou non. – rmaddy

1

Je voudrais écrire un ENUM avec une valeur brute String et une propriété calculée pour renvoyer la valeur String.Encoding appropriée. Ensuite, vous pouvez utiliser init(rawValue:) pour créer une instance.

import Foundation 

enum APITextEncoding : String 
{ 
    case iso8859_1 = "iso-8859-1" 
    // etc. 

    var encoding: String.Encoding 
    { 
     switch self 
     { 
      case .iso8859_1: 
       return .isoLatin1 
      // etc. 
     } 
    } 
} 

let receivedEncoding = APITextEncoding(rawValue: encodingDescription) 
let receivedText = String(data: receivedData, encoding: receivedEncoding.encoding) 
0

En rapide vous pouvez utiliser:

func getTextFrom(_ url: URL) -> String? { 
    guard let data = try? Data(contentsOf: url) else { 
     return nil 
    } 
    return String(data: data, encoding: .utf8) ?? 
     String(data: data, encoding: .isoLatin1) 
}