Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AltConf report - Hakata.swift #8

AltConf report - Hakata.swift #8

はるふ

June 25, 2019
Tweet

More Decks by はるふ

Other Decks in Programming

Transcript

  1. A story of Mysterious Asian Strings (for iOS) AltConf SanJose

    2019 LINE Fukuoka Tomoki Yamaguchi a.k.a. @ha1f
  2. Tomoki Yamaguchi @_ha1f • iOS Developer from Japan! • Working

    for LINE Fukuoka (Communication application) • Call me “half”
  3. How do you work with asian characters? • Even Amazon,

    Apple have problems ϑΟϧλʔ filter Ωϟϯηϧ Cancel
  4. Full-width, Half-width • Most Japanese, Chinese, Korean characters are full-width

    AB12 ̖̗̍̎ ͑ͼұ್ • Alphabets, numbers have both styles
  5. Vertical Form • Japanese, Chinese, Korean can be represented with

    vertical form • Supported by Kindle ॎ ॻ ͖ ͷ ৔ ߹ ͸ ӈ ͔ Β ࠨ ʹ ಡ Έ · ͢ ԣॻ͖ͷ৔߹͸ ࠨ͔Βӈʹ ಡΈ·͢ Vertical Scroll Horizontal Scroll
  6. Thai language sometimes exceeds UILabel • CALayer.clipToBounds will cut them

    • We should not set “clipToBounds” • Basically Thai language specific
  7. Counting characters • There are many ways to count characters

    e.g. UTF-8, grapheme cluster, unicode scalar, width, … • Apple’s default (String.count) is grapheme cluster
  8. Asian Strings are not so easy • Each method returns

    a different length • “.count” is more likely to return what you expect! i.e. user-friendly (recommended)
  9. Thai language counting • We should also restrict with memory

    size • Grapheme cluster counting returns 1
  10. Can you find a bug? Suppose we want to prevent

    from inputting text longer than 3 characters // Forbid text longer than 3 func textField( _ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String ) -> Bool { return (textField.text?.count ?? 0) < 3 }
  11. Character conversion • One character can be a combination of

    multiple characters • Even insert / delete don’t change the characters count • Works like replacing
  12. We have to validate String after change • We have

    to check characters limit after change func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let currentText = textField.text ?? "" let newText = (currentText as NSString) .replacingCharacters(in: range, with: string) return newText.count <= 3 }
  13. Even this has a bug! func textField(_ textField: UITextField, shouldChangeCharactersIn

    range: NSRange, replacementString string: String) -> Bool { let currentText = textField.text ?? "" let newText = (currentText as NSString) .replacingCharacters(in: range, with: string) return newText.count <= 3 }
  14. Even this has a bug! func textField(_ textField: UITextField, shouldChangeCharactersIn

    range: NSRange, replacementString string: String) -> Bool { let currentText = textField.text ?? "" let newText = (currentText as NSString) .replacingCharacters(in: range, with: string) return newText.count <= 3 } Let’s check the value here
  15. Result of “replacingCharacters” can be wrong • Input and Output

    do not match • The result can be shortened after confirmation Don’t trust intermediate text Don’t prevent input during editing!! ͔͍͸ͭ͠Ό → ։ൃऀ
  16. We have to validate String after change • We have

    to limit characters after confirmation override func viewDidLoad() { super.viewDidLoad() textField.addTarget(self, action: #selector(handleChange(_:)), for: .editingDidEnd) } @objc func handleChange(_ textField: UITextField) { textField.text = textField.text.map { String($0.prefix(3)) } }
  17. Conclusion 1. Be careful for character’s width and height 2.

    Be careful for counting strategy 3. Don’t block input during editing