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

noteのiOSアプリで実装したアクセシビリティの全て #iosdc #a /a11y_with_iOS_App_on_note

249b3122eee454c0a818bfe7851418e4?s=47 fromkk
September 18, 2021

noteのiOSアプリで実装したアクセシビリティの全て #iosdc #a /a11y_with_iOS_App_on_note

iOSDC Japan 2021で登壇した資料です。

----CfP----
noteのiOSアプリはここ1年間で大きな変化を遂げました。
元々30%程度だったSwift率が90%を超え、デバイスもiPhoneの縦画面のみの対応でしたがiPadの複数ウィンドウにも対応しました。
このように目に見えるカイゼンを進めてきた私たちですが、あるきっかけで目に見えない課題があることを知りました。
アクセシビリティ機能を駆使して私たちのアプリを利用してくれている方からお問い合わせをいただいたのです。
この方の日頃の利用方法についてインタビューさせていただくことになり、今まで見えていなかった課題に気づくことができました。
そこでアクセシビリティの有識者に力を借りながら、Voice OverやDynamic Typeといったアクセシビリティの助けとなる機能にも対応をはじめました。
・Voice Overを利用するとさわれると思っているUI要素にさわれない
・わかりやすいと思っていたボタンなのにVoice Overを通すと何のボタンなのか理解ができない
このトークではこういった課題を認知して、実際に対応したことをまとめてお話します。

249b3122eee454c0a818bfe7851418e4?s=128

fromkk

September 18, 2021
Tweet

Transcript

  1. 1

  2. 2

  3. 3

  4. note inc. ೥݄ελʔτ 4

  5. note inc. cakes͸ଟ਺ͷΫϦΤΠλʔ΍ग़൛ࣾͱఏܞ͍ͯ͠Δίϯςϯπ഑৴αΠτ Ͱ͢ɻಡऀͱΫϦΤΠλʔΛΑΓ਎ۙʹ݁ͼ͚ͭΔ͜ͱͰɺίϯςϯπͱͷ ৽͍͠ग़ձ͍ͷ৔Λఏڙ͠·͢ɻ 5

  6. note inc. ೥݄ελʔτ 6

  7. note inc. ΫϦΤΠλʔ͕จষ΍ը૾ɺԻ੠ɺಈըΛ౤ߘͯ͠ɺϢʔβʔ͕ͦͷίϯςϯπΛ ָ͠ΜͰԠԉͰ͖ΔϝσΟΞϓϥοτϑΥʔϜɻͩΕ΋͕૑࡞Λָ͠ΜͰଓ͚ΒΕ ΔΑ͏ɺ҆৺Ͱ͖Δงғؾ΍ɺଟ༷ੑΛେ੾ʹ͍ͯ͠·͢ɻ 7

  8. note inc. ϛογϣϯ ͩΕ΋͕૑࡞Λ͸͡Ίɺ ଓ͚ΒΕΔΑ͏ʹ͢Δɻ 8

  9. ΞΫηγϏϦςΟ 9

  10. ΢ΣϒΞΫηγϏϦςΟج൫ҕһձ 
 https://waic.jp/knowledge/accessibility/ “ҰൠʹΞΫηγϏϦςΟͱ͸ɺΞΫηεͷ͠΍͢͞Λҙຯ͠·͢ɻస ͯ͡ɺ੡඼΍αʔϏεͷར༻͠΍͢͞ͱ͍͏ҙຯͰ΋࢖ΘΕ·͢ɻ” ΞΫηγϏϦςΟ 10

  11. ΞΫηγϏϦςΟ • ো֐ऀ΍ߴྸऀ޲͚ͷରԠͱࢥΘΕ͕͕ͪͩɺશਓྨ͕৘ใʹ৮ΕͨΓػೳΛମݧ Ͱ͖Δ͜ͱΛ໨ࢦ͢ • ಛʹը໘Λཁ͢Δ΢ΣϒαΠτ΍εϚʔτϑΥϯΞϓϦέʔγϣϯʹ͓͍ͯ͸ɺࢹ֮ ো֐Λ࣋ͭਓ΍ࢹྗ͕௿Լͨ͠ਓʹෆศΛײͤͯ͡͞͠·͏͜ͱ͕ଟ͍ͨΊɺࢹ֮ తͳαϙʔτΛߦ͏͜ͱ͕த৺ͱͳΔ • ྫ:

    ը໘ͷಡΈ্͛ػೳ΍ɺը໘΍ϑΥϯτͷ֦େػೳΛαϙʔτ • ͜ͷൃදͰ΋AppleϓϥοτϑΥʔϜͷΞΫηγϏϦςΟʹؔ͢ΔػೳͰ͋Δ VoiceOverΛத৺ʹ঺հ 11
  12. ΢ΣϒΞΫηγϏϦςΟͷ4ͭͷݪଇ • ஌֮Մೳ • ৘ใٴͼϢʔβΠϯλϑΣʔείϯϙʔωϯτ͸ɺར༻ऀ͕஌֮Ͱ͖Δํ๏Ͱར༻ऀʹఏࣔՄೳͰͳ ͚Ε͹ͳΒͳ͍ɻ • ૢ࡞Մೳ • ϢʔβΠϯλϑΣʔείϯϙʔωϯτٴͼφϏήʔγϣϯ͸ૢ࡞ՄೳͰͳ͚Ε͹ͳΒͳ͍ɻ

    • ཧղՄೳ • ৘ใٴͼϢʔβΠϯλϑΣʔεͷૢ࡞͸ཧղՄೳͰͳ͚Ε͹ͳΒͳ͍ɻ • ݎ࿚ੑ • ίϯςϯπ͸ɺࢧԉٕज़ΛؚΉ༷ʑͳϢʔβΤʔδΣϯτ͕࣮֬ʹղऍͰ͖ΔΑ͏ʹे෼ʹݎ࿚Ͱͳ ͚Ε͹ͳΒͳ͍ɻ 12 https://waic.jp/docs/UNDERSTANDING-WCAG20/intro.html
  13. ϢʔβʔϏϦςΟͱͷؔ܎ • ࢖͍΍͢͞ͱ͍͏ίϯςΩετͰΑ͘ར༻͞ΕΔ͕ϢʔβʔϏ ϦςΟ͸ΞΫηγϏϦςΟ͕อͨΕ্ͨͰҙ͍ࣝͨ͠ • ͦ΋ͦ΋ΞΫηεͰ͖ͳ͚Ε͹ར༻͕Ͱ͖ͳ͍ͨΊ 13

  14. ϢʔβʔϏϦςΟͱͷؔ܎ • ࢖͍΍͢͞ͱ͍͏ίϯςΩετͰΑ͘ར༻͞ΕΔ͕ϢʔβʔϏ ϦςΟ͸ΞΫηγϏϦςΟ͕อͨΕ্ͨͰҙ͍ࣝͨ͠ • ͦ΋ͦ΋ΞΫηεͰ͖ͳ͚Ε͹ར༻͕Ͱ͖ͳ͍ͨΊ 14 ϢʔβʔϏϦςΟ ΞΫηγϏϦςΟ

  15. ΠϯΫϧʔγϒσβΠϯ • ॅΜͰ͍Δ৔ॴ΍೥୅ɺੑผͳͲʹΑΔจԽͷҧ͍ • ࿩ͨ͠Γฉ͍ͨΓɺॻ͍ͨΓಡΜͩΓ͢Δݴޠ 15 https://developer.apple.com/videos/play/wwdc2021/10275/ https://developer.apple.com/videos/play/wwdc2021/10304/ ͳͲ͜Ε·Ͱഉআ͞Ε͍ͯͨਓʑΛר͖ࠐΈͳ͕ΒแׅతʹσβΠϯ͢Δ ख๏

    ΞΫηγϏϦςΟ΍ϢʔβʔϏϦςΟ +
  16. ͳͥ ͰΞΫηγϏϦςΟ ͷ޲্ʹऔΓ૊Έ࢝Ί͔ͨ 16

  17. औΓ૊Έ࢝Ί͖͔͚ͨͬ • ࣾ಺͔ΒΞΫηγϏϦςΟΛ޲্͍ͨ͠ͱ͍͏੠্͕͕Δ • ΋ͱ΋ͱΞΫηγϏϦςΟͷ޲্ʹڵຯ͕͋ͬͨ • ۀ຿ҕୗͱ͍͏ܗͰΞΫηγϏϦςΟʹؔ͢ΔΞυόΠεΛ͘ΕΔํ͕ δϣΠϯ • noteͷ7प೥ه೦ΠϕϯτͰΞΫηγϏϦςΟʹ΋ྗΛೖΕΔࢫΛൃද

    • ໡໨ͷํ͔Βͷ໰͍߹Θ͕ͤ͋ΓϢʔβʔΠϯλϏϡʔΛ࣮ࢪ 17
  18. औΓ૊Έ࢝Ί͖͔͚ͨͬ • ࣾ಺͔ΒΞΫηγϏϦςΟΛ޲্͍ͨ͠ͱ͍͏੠্͕͕Δ • ΋ͱ΋ͱΞΫηγϏϦςΟͷ޲্ʹڵຯ͕͋ͬͨ • ۀ຿ҕୗͱ͍͏ܗͰΞΫηγϏϦςΟʹؔ͢ΔΞυόΠεΛ͘ΕΔํ͕ δϣΠϯ • noteͷ7प೥ه೦ΠϕϯτͰΞΫηγϏϦςΟʹ΋ྗΛೖΕΔࢫΛൃද

    • ໡໨ͷํ͔Βͷ໰͍߹Θ͕ͤ͋ΓϢʔβʔΠϯλϏϡʔΛ࣮ࢪ 18
  19. ໡໨ͷํ΁ͷΠϯλϏϡʔΛ࣮ࢪ • ZoomͰ࣮ࢪ • ීஈͲͷΑ͏ʹnoteΛར༻͍ͯ͠Δ͔ • noteͰࠔ͍ͬͯΔ͜ͱ͕ͳ͍͔ 19

  20. ໡໨ͷํ΁ͷΠϯλϏϡʔΛ࣮ࢪ • ZoomͰ࣮ࢪ • ීஈͲͷΑ͏ʹnoteΛར༻͍ͯ͠Δ͔ • noteͰࠔ͍ͬͯΔ͜ͱ͕ͳ͍͔ • iOSΞϓϦͰهࣄʹݟग़͠ը૾͕ઃఆͰ͖ͳ͍ •

    هࣄΛެ։͢Δࡍʹϋογϡλάͷઃఆ͕͏·͍͔͘ͳ͍ 20
  21. هࣄʹݟग़͠ը૾͕ઃఆͰ͖ͳ͍༷ࢠ 21

  22. هࣄΛެ։͢Δࡍʹϋογϡλάͷઃఆ͕͏·͍͔͘ͳ͍༷ࢠ 22

  23. ͜ΕΒͷ༷ࢠΛݟͯࢥ͍·ͨ͠ 23

  24. όά΍Μ… 24

  25. ଊ͑ํͷมԽ • ͜Ε·Ͱ͸ΞΫηγϏϦςΟΛ޲্ͤ͞Α͏ͱࢥͬͯ΋Ͳ͏ߦಈ͠ ͍͍ͯͷ͔෼͔Βͳ͔ͬͨ • ࣮ࡍʹಈ༷͘ࢠΛݟΔ͜ͱͰɺͨͩͷෆ۩߹ͩͱଊ͑ΒΕΔΑ͏ʹ • ΞΫηγϏϦςΟ޲্Λܝ͛ͯ΋ͳ͔ͳ͔λεΫ͸ਐΈਏ͍ • 1ͭͷόάमਖ਼ͱ͍͏λεΫʹ෼ղ͢Ε͹༏ઌ౓্͕͕ͬͯ͘Δ

    25
  26. VoiceOverͷ࢖͍ํ 26

  27. VoiceOverͷ੾Γସ͑ํ๏ 27

  28. VoiceOverͷ؆୯ͳ࢖͍ํ 28

  29. https://developer.apple.com/videos/play/wwdc2018/226/ “VoiceOver: App Testing Beyond The Visuals” 29

  30. ࣮ࡍʹൃੜͨ͠໰୊ͱͦͷղܾํ๏ 30

  31. ࣮ࡍʹൃੜͨ͠໰୊ͱͦͷղܾํ๏ • tapGestureRecognizer͕ઃఆ͞Ε͍ͯΔUIView͕બ୒Ͱ ͖ͳ͍໰୊ • ը૾ͷΈͷϘλϯͰҙਤ͠ͳ͍ಡΈ্͕͛͞Εͯ͠·͏໰୊ • ϋʔϑϞʔμϧ͕ด͡ΒΕͳ͍໰୊ 31

  32. tapGestureRecognizer͕ઃఆ͞ Ε͍ͯΔUIView͕બ୒Ͱ͖ͳ͍໰୊ 32

  33. ίʔυΠϝʔδ lazy var containerView: UIView = { let view =

    UIView(frame: view.bounds) view.isUserInteractionEnabled = true view.addGestureRecognizer( UITapGestureRecognizer(target: self, action: #selector(tap(sender:)))) return view }() @objc private func tap(sender: UITapGestureRecognizer) { showTappedAlert() } 33
  34. tapGestureRecognizer͕ ઃఆ͞Ε͍ͯΔUIView͕બ୒Ͱ͖ͳ͍໰୊ 34

  35. मਖ਼಺༰ view.isAccessibilityElement = true + 35

  36. tapGestureRecognizer͕ ઃఆ͞Ε͍ͯΔUIView͕બ୒Ͱ͖ͳ͍໰୊मਖ਼൛ 36

  37. ը૾ͷΈͷϘλϯͰҙਤ͠ͳ͍ ಡΈ্͕͛͞Εͯ͠·͏໰୊ 37

  38. ίʔυΠϝʔδ lazy var button: UIButton = { let button =

    UIButton(type: .custom) let configuration = UIImage.SymbolConfiguration( font: UIFont.systemFont(ofSize: 280)) let image = UIImage(systemName: "heart", withConfiguration: configuration) button.setImage(image, for: .normal) return button }() 38
  39. ը૾ͷΈͷϘλϯ͕ ҙਤ͠ͳ͍ಡΈ্͕͛͞Εͯ͠·͏໰୊ 39

  40. मਖ਼಺༰ button.accessibilityLabel = "εΩ" + 40

  41. ը૾ͷΈͷϘλϯ͕ ҙਤ͠ͳ͍ಡΈ্͕͛͞Εͯ͠·͏໰୊मਖ਼൛ 41

  42. ϋʔϑϞʔμϧ͕ด͡ΒΕͳ͍໰୊ 42

  43. ϋʔϑϞʔμϧ͕ด͡ΒΕͳ͍໰୊ 43

  44. मਖ਼಺༰ 1 lazy var closeButton: UIButton = { let button

    = UIButton(type: .custom) button.setTitle("ด͡Δ", for: .normal) button.addTarget(self, action: #selector(close(sender:)), for: .touchUpInside) return button }() @objc private func close(sender: Any) { dismiss(animated: true) } 44
  45. मਖ਼಺༰ 2 private var cancellable: AnyCancellable? private func subscribeVoiceOver() {

    cancellable?.cancel() cancellable = NotificationCenter.default.publisher( for: UIAccessibility.voiceOverStatusDidChangeNotification ) .sink { [weak self] _ in self?.handleVoiceOverStatus() } } private func handleVoiceOverStatus() { closeButton.isHidden = !UIAccessibility.isVoiceOverRunning } 45
  46. ϋʔϑϞʔμϧ͕ ด͡ΒΕΔΑ͏ʹमਖ਼൛ 46

  47. ߋʹମݧΛ޲্ͤ͞Δ6ͭͷࢪࡦ 47

  48. ߋʹମݧΛ޲্ͤ͞Δ6ͭͷࢪࡦ • ϑΥʔΧε͕౰͍ͨͬͯΔཁૉͰԿ͕Ͱ͖Δͷ͔Λ஌Β͍ͤͨ • Կ͔ಈ࡞Λͨ͠Β༻ҙͨ͠ςΩετΛಡΈ্͍͛ͨ • Կ͔ಈ࡞Λͨ͠ࡍʹϑΥʔΧε͞ΕΔ৔ॴΛࢦఆ͍ͨ͠ • ೔෇ͷಡΈ্͛ΛࣗવʹରԠ͍ͨ͠ •

    Ϧετը໘ͰεΠονͷON/OFFͷૢ࡞Λࣗવʹ͍ͨ͠ • ݟग़͠δϟϯϓػೳ΁ͷରԠΛ͍ͨ͠ 48
  49. ϑΥʔΧε͕౰͍ͨͬͯΔཁૉͰ Կ͕Ͱ͖Δͷ͔Λ஌Β͍ͤͨ 49

  50. 50 Կ͕Ͱ͖Δͷ͔͕෼͔Βͳ͍༷ࢠ

  51. ରԠ಺༰ 51 cell.accessibilityHint = "μϒϧλοϓͰ࡟আ" +

  52. 52 Կ͕Ͱ͖Δͷ͔͕෼͔ΔΑ͏ʹͳ༷ͬͨࢠ

  53. Կ͔ಈ࡞Λͨ͠Β༻ҙͨ͠ςΩετ ΛಡΈ্͍͛ͨ 53

  54. ίʔυΠϝʔδ 54 private func showErrorMessage(_ errorMessage: String) { errorLabel.text =

    errorMessage }
  55. 55 Τϥʔ͕දࣔ͞Εͯ΋ ؾ͚ͮͳ͍༷ࢠ

  56. ରԠ಺༰ 56 private func showErrorMessage(_ errorMessage: String) { errorLabel.text =

    errorMessage UIAccessibility.post(notification: .announcement, argument: errorMessage) } + https://developer.apple.com/documentation/uikit/uiaccessibility/notification
  57. 57 Τϥʔ͕දࣔ͞Ε͍ͯΔ͜ͱʹ ؾ͚ͮΔΑ͏ʹͳ༷ͬͨࢠ

  58. Կ͔ಈ࡞Λͨ͠ࡍʹϑΥʔΧε ͞ΕΔ৔ॴΛࢦఆ͍ͨ͠ 58

  59. Կ͔ಈ࡞Λͨ͠ࡍʹϑΥʔΧε͞ΕΔ৔ॴΛࢦఆ͍ͨ͠ 59

  60. मਖ਼಺༰ @objc private func next(sender: Any) { UIAccessibility.post(notification: .layoutChanged, argument:

    messageLabel) } + 60 https://developer.apple.com/documentation/uikit/uiaccessibility/notification
  61. Կ͔ಈ࡞Λͨ͠ࡍʹϑΥʔΧε͞ΕΔ৔ॴΛࢦఆ͍ͨ͠ରԠ൛ 61

  62. ೔෇ͷಡΈ্͛ΛࣗવʹରԠ͍ͨ͠ 62

  63. ίʔυΠϝʔδ1 lazy var dateLabel: UILabel = { let label =

    UILabel() label.textColor = .label label.font = UIFont.preferredFont(forTextStyle: .headline) label.textAlignment = .center label.numberOfLines = 0 label.lineBreakMode = .byWordWrapping return label }() 
 
 private func showNow() { dateLabel.text = dateFormatter.string(from: now) } 63
  64. ίʔυΠϝʔδ2 private lazy var dateFormatter: DateFormatter = { guard let

    dateFormat = DateFormatter.dateFormat( fromTemplate: "yyyy/MM/dd HH:mm", options: 0, locale: .current) else { fatalError("failed get date format from template") } var calendar = Calendar(identifier: .gregorian) let timeZone = TimeZone.current let locale = Locale.current calendar.locale = locale var dateFormatter = DateFormatter() dateFormatter.calendar = calendar dateFormatter.timeZone = timeZone dateFormatter.locale = locale dateFormatter.dateFormat = dateFormat return dateFormatter }() 64
  65. 65 ೔෇ͷಡΈ্͛ΛࣗવʹରԠ͢Δલ

  66. मਖ਼಺༰ 66 private func showNow() { dateLabel.text = dateFormatter.string(from: now)

    dateLabel.accessibilityLabel = accessibilityDateFormatter.string(from: now) } private lazy var accessibilityDateFormatter: DateFormatter = { var calendar = Calendar(identifier: .gregorian) let timeZone = TimeZone.current let locale = Locale.current calendar.locale = locale var dateFormatter = DateFormatter() dateFormatter.calendar = calendar dateFormatter.timeZone = timeZone dateFormatter.locale = locale dateFormatter.dateStyle = .long dateFormatter.timeStyle = .medium return dateFormatter }() + +
  67. 67 ೔෇ͷಡΈ্͛ΛࣗવʹରԠ൛

  68. Ϧετը໘ͰεΠονͷON/OFFͷૢ࡞ Λࣗવʹ͍ͨ͠ 68

  69. 69 Ϧετը໘ͰεΠονͷON/OFFͷૢ࡞վળલ

  70. मਖ਼಺༰ 70 private func setUp() { isAccessibilityElement = true }

    
 
 override var accessibilityLabel: String? { get { titleLabel.text } set {} } override var accessibilityValue: String? { get { toggleSwitch.accessibilityValue } set {} } override var accessibilityTraits: UIAccessibilityTraits { get { toggleSwitch.accessibilityTraits } set {} } override func accessibilityActivate() -> Bool { toggleSwitch.isOn.toggle() return true } SwitchAccessibleViewCell.swift
  71. 71 Ϧετը໘ͰεΠονͷON/OFFͷૢ࡞վળޙ

  72. ݟग़͠δϟϯϓػೳ΁ͷରԠΛ͍ͨ͠ 72

  73. ϩʔλʔػೳ • “VoiceOver ϩʔλʔΛ࢖ͬͯ VoiceOver ͷಈ࡞ΛมߋͰ͖· ͢ɻVoiceOver ͷԻྔ΍࿩͢଎͞Λมߋͨ͠Γɺը໘্Ͱ߲໨ؒ ΛҠಈͨ͠Γ͢Δ͜ͱ͕Ͱ͖ɺͦͷଞͷૢ࡞΋ՄೳͰ͢ɻ” 


    https://support.apple.com/ja-jp/HT204783 • 1ຊࢦͷ্ԼεϫΠϓͰར༻Մೳ • ը໘্Λ2ຊࢦͰճ͢Α͏ʹಈ͔͢͜ͱͰઃఆΛมߋ • ΧελϜػೳΛ࡞੒͢Δ͜ͱ΋Մೳ 
 https://developer.apple.com/documentation/uikit/ uiaccessibilitycustomrotor 73
  74. ίʔυΠϝʔδ 74 private func makeHeadlineLabel(with title: String) -> UILabel {

    let label = UILabel() label.font = UIFont.preferredFont(forTextStyle: .headline) label.textColor = UIColor.label label.text = title label.numberOfLines = 0 label.lineBreakMode = .byWordWrapping return label }
  75. 75 ݟग़͠δϟϯϓػೳ΁ͷରԠલ

  76. मਖ਼಺༰ 76 private func makeHeadlineLabel(with title: String) -> UILabel {

    let label = UILabel() label.font = UIFont.preferredFont(forTextStyle: .headline) label.textColor = UIColor.label label.text = title label.numberOfLines = 0 label.lineBreakMode = .byWordWrapping label.accessibilityTraits = [.header] return label } +
  77. 77 ݟग़͠δϟϯϓػೳ΁ͷରԠޙ

  78. 78 static var none: UIAccessibilityTraits The accessibility element has no

    traits. static var button: UIAccessibilityTraits The accessibility element behaves like a button. static var link: UIAccessibilityTraits The accessibility element behaves like a link. static var image: UIAccessibilityTraits The accessibility element behaves like an image. static var searchField: UIAccessibilityTraits The accessibility element behaves like a search field. static var keyboardKey: UIAccessibilityTraits The accessibility element behaves like a keyboard key. static var staticText: UIAccessibilityTraits The accessibility element behaves like static text that can't change. static var header: UIAccessibilityTraits The accessibility element is a header that divides content into sections, such as the title of a navigation bar. static var tabBar: UIAccessibilityTraits The accessibility element behaves like a tab bar. static var summaryElement: UIAccessibilityTraits The accessibility element provides summary information when the app starts. static var selected: UIAccessibilityTraits The accessibility element is currently in a selected state. static var notEnabled: UIAccessibilityTraits The accessibility element isn't in an enabled state and doesn't respond to user interaction. static var adjustable: UIAccessibilityTraits The accessibility element allows continuous adjustment through a range of values. static var allowsDirectInteraction: UIAccessibilityTraits The accessibility element allows direct touch interaction for VoiceOver users. static var updatesFrequently: UIAccessibilityTraits The accessibility element frequently updates its label or value. static var causesPageTurn: UIAccessibilityTraits The accessibility element causes an automatic page turn when VoiceOver finishes reading the text within it. static var playsSound: UIAccessibilityTraits The accessibility element plays its own sound when the user activates it. static var startsMediaSession: UIAccessibilityTraits The accessibility element starts a media session when the user activates it. accessibilityTraits https://developer.apple.com/documentation/uikit/uiaccessibility/uiaccessibilitytraits
  79. ΞΫηγϏϦςΟͷઃఆΛ֬ೝ͢ΔTips 79

  80. ΞΫηγϏϦςΟͷઃఆΛ֬ೝ͢ΔTips • ʮԻ੠ίϯτϩʔϧʯΛ༗ޮʹͯ͠ ʮΦʔόʔϨΠʯͷઃఆΛʮ߲໨ ໊ʯʹ͢Δ͜ͱͰઃఆࡁΈͷϥϕϧ ͕ՄࢹԽͰ͖Δ • VoiceOverΛ࣮ࡍʹ࢖Θͣͱ΋ϥϕ ϧͷ֬ೝ͕Ͱ͖ͯศར 80

  81. Accessibility Inspector 81 • ΞΫηγϏϦςΟʹؔ͢ΔΑΓৄࡉ ͷ৘ใΛௐ΂Δʹ͸Xcodeʹ෇ଐͷ Accessibility InspectorΛར ༻

  82. ΞΫηγϏϦςΟʹؔ͢Δςετ • SnapshotTesting 
 https://github.com/pointfreeco/swift-snapshot-testing • AccessibilitySnapshot 
 https://github.com/cashapp/AccessibilitySnapshot •

    A11yUITests 
 https://github.com/rwapp/A11yUITests 82
  83. ར༻ऀͷ੠ • “ૉఢͳॻ͖खͱܨ͕Δ৔ॴͰ͋Γɺࢲࣗ਎͕ࣗ෼Λදݱ͢Δ৔ॴͰ͋ΔnoteͰ ͜Ε͔Β΋ॻ͍͍͖͍ͯͨɻͦͷҰาͱͯ͠ΞΫηγϏϦςΟͷվળ͸େ͖ͳྗ ʹͳͬͨɻ” 
 https://note.com/azusa_1202/n/neeeb0112c395 • “note͕ΞΫηγϏϦςΟʹऔΓ૊Ή͜ͱʹΑΓɺࢲͷΑ͏ͳεΫϦʔϯɾϦʔ μʔ࢖༻ऀ͚ͩͰͳ͘ɺ਎ମ΍ೝ஌ʹࠔ೉͞Λײ͡Δਓ΍ಡࣈো֐΍ॻࣈো֐ͳ

    Ͳɺ͍Ζ͍Ζͳ“ଟ༷ੑ”ʹԠ͑ΒΕΔαʔϏεʹ͍͍ۙͮͯ͘ͱࢥ͍·͢ɻ” 
 https://note.com/kokoa_nattsu/n/nc08f81cda989 83
  84. ࠓޙͷల๬ • ͷ΢ΣϒɾΞϓϦͷΞΫηγϏϦςΟͷ޲্׆ಈ͸·ͩ·ͩ࢝ ·ͬͨ͹͔ΓͰෆ׬શ • ΞΫηγϏϦςΟͷ޲্ʹΰʔϧ͸ͳ͍ • ఆৗͷ։ൃɾ඼࣭؅ཧͷதʹ૊ΈࠐΜͰ։ൃΛਐΊͯߦ͖͍ͨ • ఆظతʹϢʔβʔΠϯλϏϡʔ΍ΞϯέʔτͳͲΛ࣮ࢪͯ͠ར༻ऀͷ੠Λ

    र্͍͍͛ͯ͘࢓૊Έͮ͘Γ 84
  85. ·ͱΊ • ΞΫηγϏϦςΟΛ޲্͢Δͱҙؾࠐ·ͣʹόάΛमਖ਼͢Δͱ͍͏ҙࣝ • NSObject͕͍࣋ͬͯΔaccessibilityؔ࿈ϓϩύςΟ͔Β • ༻్ʹ߹ΘͤͯUIAccessibility΍Accessibility Frameworkͷ ػೳΛར༻ͯ͠ମݧΛ޲্Λ͍͚ͤͯ͞͹Αͦ͞͏ •

    ΞΫηγϒϧͳΞϓϦ͕૿͑Δ͜ͱͰɺࠔ͍ͬͯΔਓ͕গ͠Ͱ΋ݮΕ͹ 85
  86. ৘ใऩू • https://developer.apple.com/accessibility/ • https://a11yj.herokuapp.com 
 #apple-app νϟϯωϧͰAppleϓϥοτϑΥʔϜʹؔ͢Δ৘ใަ׵ • https://a11y-guidelines.orange.com/en/

    • https://accrefs.jp 
 Webʹؔ͢Δ৘ใ͕΄ͱΜͲ͚ͩͲΞϓϦ΋গ͠ 86
  87. ͰͷऔΓ૊Έ • ΞΫηγϏϦςΟڧԽͷҰ؀ͰɺεΫϦʔϯϦʔμʔʹΑΔಡΈ্͛ͷΧ ΠθϯΛߦ͍·ͨ͠ 
 https://note.com/info/n/n4dbe29c380a1 • VoiceOverɺDynamic TypeͳͲɺiOSΞϓϦͷΞΫηγϏϦςΟػೳ ͷڧԽΛߦ͍·ͨ͠

    
 https://note.com/info/n/nfcc92e285d96 • ͳͲͳͲ 87
  88. αϯϓϧίʔυ 88 https://github.com/fromkk/AccessibilitySampler

  89. 89