Swift и Wordpress API: Wordpress API переводит некоторые символы в юникод - PullRequest
2 голосов
/ 11 мая 2019

Я копирую 2 заголовка сообщения, возвращаемого Wordpress API:

Haydarpaşa’da ortaya çıktı! Tam 1700 yıllık…

Pakistan’da terör saldırısı

Я создаю структуры для категорий / сообщений и другихвещи и сделали их декодируемыми, но они не обрабатывают Unicodes.Вот пример;структура, которую я создал для категорий.(Структура сообщений слишком велика, поэтому я делюсь структурой категорий. Все они построены на одной идее.)

struct WPCategory: Decodable {

  let id: Int
  let count: Int
  let description: String
  let link: URL
  let name: String
  let slug: String
  let taxonomy: WPCategoryTaxonomy
  let parent: Int

  enum WPCategoryTaxonomy: String, Codable {
    case category, postTag = "post_tag", navMenu = "nav_menu", linkCategory = "link_category", postFormat = "post_format"
  }

  enum CodingKeys: String, CodingKey {
    case id, count, description, link, name, slug, taxonomy, parent, meta
  }

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)

    id = try container.decode(Int.self, forKey: .id)
    count = try container.decode(Int.self, forKey: .count)
    description = try container.decode(String.self, forKey: .description)
    let linkString  = try container.decode(String.self, forKey: .link)
    guard let link = URL.init(string: linkString) else {
      throw WPAPIError.urlToStringFailed
    }
    self.link = link
    name = try container.decode(String.self, forKey: .name)
    slug = try container.decode(String.self, forKey: .slug)
    taxonomy = try container.decode(WPCategoryTaxonomy.self, forKey: .taxonomy)
    parent = try container.decode(Int.self, forKey: .parent)
  }
}

Я использую Alamofire для получения данных:

  func getCategories(page: Int = 1, onCompletion completionHandler: @escaping (_ categories: [WPCategory]?, _ totalPages: Int?, _ error: Error?) -> Void) {
    let request = alamofire.request(categoriesURL, method: .get, parameters: ["page": page, "per_page": 100, "exclude":"117"], encoding: URLEncoding.httpBody).validate()
    request.responseData  { (response) in
      switch response.result {
      case .success(let result):
        guard let total = response.response?.allHeaderFields["x-wp-totalpages"] as? String else {
          completionHandler(nil, nil, WPAPIError.couldNotFetchTotalHeader)
          return
        }

        do {
          let categories = try JSONDecoder.init().decode([WPCategory].self, from: result)
          completionHandler(categories, Int(total), nil)
        } catch(let err) {
          completionHandler(nil, nil, err)
        }

      case .failure(let error):
        completionHandler(nil, nil, error)
      }
    }
  }

Итак, как мне справиться с этими символами Юникода?Есть идеи?Спасибо.

Ответы [ 3 ]

3 голосов
/ 18 мая 2019

Используйте это расширение, которое я написал для него:

extension String {
    func htmlDocument() throws -> String {
        let data = self.data(using: .unicode)
        let options: [NSAttributedString.DocumentReadingOptionKey: NSAttributedString.DocumentType] = [.documentType : .html]
        return try NSAttributedString(data: data!, options: options, documentAttributes: nil).string
    }
}

Так что вы можете использовать его в вашем декодере, как:

...
        name = try container.decode(String.self, forKey: .name).htmlDocument()
...
0 голосов
/ 14 мая 2019

Если вам нужно обработать такую ​​экранированную строку в Swift, вы можете преобразовать ее в нормальную строку Unicode.

То есть, если ввести следующий код на игровой площадке Swift:

import Foundation


func convert(escapedString: String) -> String {
    guard let regex = try? NSRegularExpression(pattern: "(&#([0-9]+);)",
                                               options: []) else { return escapedString }

    let escapedNSString = escapedString as NSString
    let matches: [NSTextCheckingResult] = regex.matches(in: escapedString,
                                                        options: [],
                                                        range: NSMakeRange(0, escapedString.count))
    var convertedString = escapedNSString

    for match in matches.reversed() {
        let matchString = escapedNSString.substring(with: match.range(at: 2))
        var replacement: String
        if let unicode = UnicodeScalar(Int(matchString)!) {
            replacement = String(unicode)
        } else {
            replacement = "?"
        }
        convertedString = convertedString.replacingCharacters(in: match.range, with: replacement) as NSString
    }
    return String(convertedString)
}


let str1 = "Haydarpaşa’da ortaya çıktı! Tam 1700 yıllık…"
print (convert(escapedString: str1))
let str2 = "Pakistan’da terör saldırısı"
print (convert(escapedString: str2))

так вы получите в результате:

Haydarpaşa’da ortaya çıktı! Tam 1700 yıllık…
Pakistan’da terör saldırısı
0 голосов
/ 14 мая 2019

В соответствии с предложением @OOper лучше обновлять заголовок и текст при использовании юникодаСтрока swift основана на юникоде и ниже приведена ссылка на документацию, подтверждающую стандартную библиотеку swift, или платформа Apple правильно обрабатывает юникод.так что упомянутые вами названия не имеют смысла … ’ это числовые ссылки на символы, а не символы Юникода.

https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html

...