Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Apple TV tvOS入門 Iosdc2017

869 views

Published on

Introduction to tvOS and focus

Published in: Software
  • Nice !! Download 100 % Free Ebooks, PPts, Study Notes, Novels, etc @ https://www.ThesisScientist.com
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Apple TV tvOS入門 Iosdc2017

  1. 1. iOSDC 2017/09/17 Yuji Hato Apple TV tvOS入門
  2. 2. About me Yuji Hato CyberAgent, Inc. / AbemaTV, Inc. dekatotoro @dekatotoro Contributed services
  3. 3. Apple TV
  4. 4. Apple TV
  5. 5. ・64-bit A8 processor ・32GB or 64GB of storage ・2GB of RAM ・10/100Mbps Ethernet ・WiFi 802.11a/b/g/n/ac ・1080p resolution ・HDMI 1.4 Apple TV 4th generation ・A10X Fusion ・32GB or 64GB of storage ・3GB of RAM ・Gigabit Ethernet ・Wi-Fi with MIMO 802.11ac ・2160p resolution ・HDMI 2.0 4K
  6. 6. 32GB 15,800円 64GB 20,800円 ※2016/09に値下げ ・32GB 18,400円 →15,800円(2,600円値下げ) ・64GB 24,800円 →20,800円(4,000円値下げ) Apple TV (tvOS) 4th generation 4K 32GB 19,800円 64GB 21,800円
  7. 7. Remote
  8. 8. https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/ Remote
  9. 9. https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/ Remote
  10. 10. Swipe Click Tap https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/ Remote
  11. 11. Development Method
  12. 12. Development Method iOSとほぼ同様に開発 ・Traditional Apps TVMLとTVJSをで開発 ・Client-Server Apps
  13. 13. Limited App Size
  14. 14. Limited App Size 200MB 4GB
  15. 15. Data Storage
  16. 16. Limited Local Storage Service Online/Local Persistent/Temporary limit iCloud Key-Value Store (KVS) Online Persistent 1MB max CloudKit Online Persistent - UserDefaults Local Persistent 500KB max Keychain Local Persistent - CacheDirectory Local Temporary May be purged TemporaryDirectory Local Temporary May be purged
  17. 17. Limited Local Storage Service Online/Local Persistent/Temporary limit iCloud Key-Value Store (KVS) Online Persistent 1MB max CloudKit Online Persistent - UserDefaults Local Persistent 500KB max Keychain Local Persistent - CacheDirectory Local Temporary May be purged TemporaryDirectory Local Temporary May be purged
  18. 18. Limited Local Storage Service Online/Local Persistent/Temporary limit iCloud Key-Value Store (KVS) Online Persistent 1MB max CloudKit Online Persistent - UserDefaults Local Persistent 500KB max Keychain Local Persistent - CacheDirectory Local Temporary May be purged TemporaryDirectory Local Temporary May be purged
  19. 19. Limited Local Storage Service Online/Local Persistent/Temporary limit iCloud Key-Value Store (KVS) Online Persistent 1MB max CloudKit Online Persistent - UserDefaults Local Persistent 500KB max Keychain Local Persistent - CacheDirectory Local Temporary May be purged TemporaryDirectory Local Temporary May be purged
  20. 20. User Interaction
  21. 21. https://developer.apple.com/tvos/human-interface-guidelines/overview/ User Interaction Focus
  22. 22. https://developer.apple.com/tvos/human-interface-guidelines/app-architecture/focus-and-selection/ Parallax User Interaction
  23. 23. https://developer.apple.com/tvos/human-interface-guidelines/visual-design/video/ Video User Interaction
  24. 24. Icons and Images
  25. 25. https://developer.apple.com/tvos/human-interface-guidelines/icons-and-images/ Icons and Images App Icon.
  26. 26. https://developer.apple.com/tvos/human-interface-guidelines/icons-and-images/app-icon/ Layered Images. Icons and Images
  27. 27. Layered Images. https://developer.apple.com/tvos/human-interface-guidelines/icons-and-images/ Icons and Images
  28. 28. https://developer.apple.com/tvos/human-interface-guidelines/icons-and-images/ Top Shelf Images. Icons and Images
  29. 29. https://developer.apple.com/tvos/human-interface-guidelines/icons-and-images/ Top Shelf Images. Icons and Images
  30. 30. Layout
  31. 31. Layout 1920 x 1080 3840 x 21604K
  32. 32. https://developer.apple.com/tvos/human-interface-guidelines/visual-design/ Layout
  33. 33. https://support.apple.com/ja-jp/HT202763 Layout
  34. 34. https://developer.apple.com/tvos/human-interface-guidelines/visual-design/ Layout
  35. 35. https://developer.apple.com/tvos/human-interface-guidelines/visual-design/ Layout
  36. 36. https://developer.apple.com/tvos/human-interface-guidelines/visual-design/layout/ Layout
  37. 37. Interface Elements
  38. 38. Tab Bars Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  39. 39. TableView Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  40. 40. CollectionView Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  41. 41. Split Views Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  42. 42. Text Fields Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  43. 43. Keyboards Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  44. 44. Search Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  45. 45. Button Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  46. 46. Navigation Bars Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  47. 47. Navigation Bars Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  48. 48. Page Controls Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  49. 49. Activity Indicators Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  50. 50. Alerts Interface Elements https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/
  51. 51. Gesture
  52. 52. Gesture
  53. 53. Gesture • Swipe • Touch • Select
  54. 54. Gesture UITapGestureRecognizer • upArrow • downArrow • leftArrow • rightArrow • select • menu • playPause
  55. 55. Gesture UITapGestureRecognizer let gesture = UITapGestureRecognizer(target: self, action: #selector(menuButtonPressed(_:))) gesture.allowedPressTypes = [NSNumber(value: UIPressType.menu.rawValue)] view.addGestureRecognizer(gesture)
  56. 56. Gesture UITapGestureRecognizer gesture.allowedPressTypes = [NSNumber(value: UIPressType.menu.rawValue)]
  57. 57. Gesture UISwipeGestureRecognizer • right • left • up • down
  58. 58. Gesture let gesture = UISwipeGestureRecognizer(target: self, action: #selector(swipeUp(_:))) gesture.direction = .up view.addGestureRecognizer(gesture) UISwipeGestureRecognizer
  59. 59. Gesture gesture.direction = .up UISwipeGestureRecognizer
  60. 60. Focus
  61. 61. https://developer.apple.com/tvos/human-interface-guidelines/overview/ Focus
  62. 62. Focus Focusはいつ更新されるの?
  63. 63. Focus • システムが更新を要求したとき • ユーザーの操作 • アプリケーションが更新を要求したとき
  64. 64. Focus Focusは誰が更新するの?
  65. 65. Focus https://developer.apple.com/library/content/documentation/General/Conceptual/AppleTV_PG/WorkingwiththeAppleTVRemote.html Focus Engine
  66. 66. Focus Focus Engineが検索する範囲は、現在Focusされて いるViewの大きさに応じて決まり、そのViewを起点 として、動きの方向にあるFocus可能な領域を見つけ て更新 Focus Engine
  67. 67. Focus Focus Engineは、View階層のFocus動作を定義する UIFocusEnvironmentプロトコルに従ってFocusを制 御 Focus Engine
  68. 68. Focus https://devstreaming-cdn.apple.com/videos/wwdc/2017/224sn8vw625k1e86/224/224_focus_interaction_in_tvos_11.pdf UIFocusEnvironment
  69. 69. Focus public var preferredFocusEnvironments: [UIFocusEnvironment] { get } public func shouldUpdateFocus(in context: UIFocusUpdateContext) -> Bool public func setNeedsFocusUpdate() public func updateFocusIfNeeded() public func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) @available(tvOS 11.0, *) optional public func soundIdentifierForFocusUpdate(in context: UIFocusUpdateContext) -> UIFocusSoundIdentifier? UIFocusEnvironmentプロトコル
  70. 70. Focus public var preferredFocusEnvironments: [UIFocusEnvironment] { get } UIFocusEnvironmentプロトコル
  71. 71. Focus public func shouldUpdateFocus(in context: UIFocusUpdateContext) -> Bool UIFocusEnvironmentプロトコル
  72. 72. Focus public func setNeedsFocusUpdate() public func updateFocusIfNeeded() UIFocusEnvironmentプロトコル
  73. 73. Focus public func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) UIFocusEnvironmentプロトコル
  74. 74. Focus https://devstreaming-cdn.apple.com/videos/wwdc/2017/224sn8vw625k1e86/224/224_focus_interaction_in_tvos_11.pdf UIFocusEnvironment
  75. 75. Focus @available(tvOS 11.0, *) optional public func soundIdentifierForFocusUpdate(in context: UIFocusUpdateContext) -> UIFocusSoundIdentifier? UIFocusEnvironmentプロトコル
  76. 76. Focus UIFocusEnvironmentに準拠しているクラス
  77. 77. Focus • UIView • UIViewController • UIPresentationController
  78. 78. Focus @available(tvOS 10.0, *) public protocol UIFocusItem : UIFocusEnvironment { public var canBecomeFocused: Bool { get } } UIFocusItemプロトコル
  79. 79. Focus Focus可能なUIKitのクラス
  80. 80. Focus • UIButton • UITextField • UITableView • UICollectionView • UITextView • UISegmentedControl • UISearchBar • etc..
  81. 81. Focus https://devstreaming-cdn.apple.com/videos/wwdc/2017/224sn8vw625k1e86/224/224_focus_interaction_in_tvos_11.pdf
  82. 82. Focus UILabelなどデフォルトでフォーカスされないViewを フォーカスさせるには?
  83. 83. Focus class CustomLabel: UILabel { isUserInteractionEnabled = true isUserInteractionEnabled = true override var canBecomeFocused: Bool { return true } } } } UILabel for Focus
  84. 84. Focus override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) { super.didUpdateFocus(in: context, with: coordinator) // Focus if context.nextFocusedView == self { coordinator.addCoordinatedFocusingAnimations({ [weak self] context in self?.transform = CGAffineTransform(scaleX: 1.4, y: 1.4) }, completion: nil) } // UnFocus if context.previouslyFocusedView == self { coordinator.addCoordinatedUnfocusingAnimations({ [weak self] context in self?.transform = CGAffineTransform.identity }, completion: nil) } } UILabel for Focus
  85. 85. Focus // Focus if context.nextFocusedView == self { coordinator.addCoordinatedFocusingAnimations({ [weak self] context in self?.transform = CGAffineTransform(scaleX: 1.4, y: 1.4) }, completion: nil) } UILabel for Focus
  86. 86. Focus // UnFocus if context.previouslyFocusedView == self { coordinator.addCoordinatedUnfocusingAnimations({ [weak self] context in self?.transform = CGAffineTransform.identity }, completion: nil) } UILabel for Focus
  87. 87. Focus UILabel for Focus
  88. 88. Focus UITableView, UICollectionViewのFocusは?
  89. 89. Focus Focus用のdelegateがtvOS用にあります
  90. 90. Focus UITableViewDelegate for Focus @available(tvOS 9.0, *) optional public func tableView(_ tableView: UITableView, canFocusRowAt indexPath: IndexPath) -> Bool @available(tvOS 9.0, *) optional public func tableView(_ tableView: UITableView, shouldUpdateFocusIn context: UITableViewFocusUpdateContext) -> Bool @available(tvOS 9.0, *) optional public func tableView(_ tableView: UITableView, didUpdateFocusIn context: UITableViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) @available(tvOS 9.0, *) optional public func indexPathForPreferredFocusedView(in tableView: UITableView) -> IndexPath?
  91. 91. Focus @available(tvOS 9.0, *) optional public func collectionView(_ collectionView: UICollectionView, canFocusItemAt indexPath: IndexPath) -> Bool @available(tvOS 9.0, *) optional public func collectionView(_ collectionView: UICollectionView, shouldUpdateFocusIn context: UICollectionViewFocusUpdateContext) -> Bool @available(tvOS 9.0, *) optional public func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) @available(tvOS 9.0, *) optional public func indexPathForPreferredFocusedView(in collectionView: UICollectionView) -> IndexPath? @available(tvOS 9.0, *) optional public func collectionView(_ collectionView: UICollectionView, targetIndexPathForMoveFromItemAt originalIndexPath: IndexPath, toProposedIndexPath proposedIndexPath: IndexPath) -> IndexPath @available(tvOS 9.0, *) optional public func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint UICollectionViewDelegate for Focus
  92. 92. Focus @available(tvOS 9.0, *) open var remembersLastFocusedIndexPath: Bool UITableView, UICollectionView for Focus
  93. 93. Focus UIImageViewのFocusは?
  94. 94. Focus @available(tvOS 9.0, *) open var adjustsImageWhenAncestorFocused: Bool @available(tvOS 9.0, *) open var focusedFrameGuide: UILayoutGuide { get } @available(tvOS 11.0, *) open var overlayContentView: UIView { get } @available(tvOS 11.0, *) open var masksFocusEffectToContents: Bool UIImageView for Focus
  95. 95. Focus @available(tvOS 9.0, *) open var adjustsImageWhenAncestorFocused: Bool UIImageView for Focus
  96. 96. Focus imageView.adjustsImageWhenAncestorFocused = true UIImageView for Focus https://developer.apple.com/tvos/human-interface-guidelines/overview/focus-and-parallax/
  97. 97. Focus UIImageView for Focus @available(tvOS 11.0, *) open var overlayContentView: UIView { get }
  98. 98. Focus UIImageView for Focus
  99. 99. Focus let overlayView = UIView(frame: imageView.frame) overlayView.backgroundColor = UIColor.black.withAlphaComponent(0.5) imageView.overlayContentView.addSubview(overlayView) UIImageView for Focus
  100. 100. Focus imageView.overlayContentView.addSubview(overlayView) UIImageView for Focus
  101. 101. Focus // UICollectionView delegate func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) { // Focus if let cell = context.nextFocusedView as? CostomCollectionViewCell { coordinator.addCoordinatedFocusingAnimations({ context in cell.imageView.overlayContentView.alpha = 0 }, completion: nil) } // UnFocus if let cell = context.previouslyFocusedView as? CostomCollectionViewCell { coordinator.addCoordinatedUnfocusingAnimations({ context in cell.imageView.overlayContentView.alpha = 1 }, completion: nil) } } UIImageView for Focus
  102. 102. Focus // Focus if let cell = context.nextFocusedView as? CostomCollectionViewCell { coordinator.addCoordinatedFocusingAnimations({ context in cell.imageView.overlayContentView.alpha = 0 }, completion: nil) } UIImageView for Focus
  103. 103. Focus // UnFocus if let cell = context.previouslyFocusedView as? CostomCollectionViewCell { coordinator.addCoordinatedUnfocusingAnimations({ context in cell.imageView.overlayContentView.alpha = 1 }, completion: nil) } UIImageView for Focus
  104. 104. Focus UIImageView for Focus
  105. 105. Focus Focus Update Notification
  106. 106. Focus Focus Update Notification extension NSNotification.Name { @available(tvOS 11.0, *) public static let UIFocusDidUpdate: NSNotification.Name @available(tvOS 11.0, *) public static let UIFocusMovementDidFail: NSNotification.Name } @available(tvOS 11.0, *) public let UIFocusUpdateContextKey: String @available(tvOS 11.0, *) public let UIFocusUpdateAnimationCoordinatorKey: String
  107. 107. Focus Focus Update Notification @available(tvOS 11.0, *) public static let UIFocusDidUpdate: NSNotification.Name
  108. 108. Focus Focus Update Notification @available(tvOS 11.0, *) public static let UIFocusMovementDidFail: NSNotification.Name }
  109. 109. Focus UIFocusGuide?
  110. 110. Focus @available(tvOS 9.0, *) open class UIFocusGuide : UILayoutGuide { open var isEnabled: Bool @available(tvOS 10.0, *) open var preferredFocusEnvironments: [UIFocusEnvironment]! } UIFocusGuide
  111. 111. Focus UIFocusGuide
  112. 112. Focus UIFocusGuide
  113. 113. Focus UIFocusGuide
  114. 114. Focus UIFocusGuide
  115. 115. Focus UIFocusGuide
  116. 116. Focus UIFocusGuide FocusGuide
  117. 117. Focus UIFocusGuide FocusGuide preferredFocusEnvironments
  118. 118. Focus UIFocusGuide
  119. 119. Focus focusGuide = UIFocusGuide() view.addLayoutGuide(focusGuide) // Anchor the top left of the focus guide. focusGuide.topAnchor.constraint(equalTo: button.topAnchor).isActive = true focusGuide.leftAnchor.constraint(equalTo: collectionView.leftAnchor).isActive = true // Anchor the width and height of the focus guide. focusGuide.heightAnchor.constraint(equalTo: button.heightAnchor).isActive = true focusGuide.widthAnchor.constraint(equalTo: collectionView.widthAnchor).isActive = true focusGuide.preferredFocusEnvironments = [button] UIFocusGuide
  120. 120. Focus focusGuide = UIFocusGuide() view.addLayoutGuide(focusGuide) UIFocusGuide
  121. 121. Focus // Anchor the top left of the focus guide. focusGuide.topAnchor.constraint(equalTo: button.topAnchor).isActive = true focusGuide.leftAnchor.constraint(equalTo: collectionView.leftAnchor).isActive = true UIFocusGuide
  122. 122. Focus // Anchor the width and height of the focus guide. focusGuide.heightAnchor.constraint(equalTo: button.heightAnchor).isActive = true focusGuide.widthAnchor.constraint(equalTo: collectionView.widthAnchor).isActive = true UIFocusGuide
  123. 123. Focus focusGuide.preferredFocusEnvironments = [button] UIFocusGuide
  124. 124. Focus Focusがうまくいかない場合
  125. 125. Focus • canBecomeFocusedがfalseになってないか • isHiddenがtrueになってないか • alphaが0でないか • isUserInteractionEnabledがfalseになってないか • viewが隠れていないか Focusがうまくいかない場合
  126. 126. Focus Focusのdebug
  127. 127. Focus Focus Update Logging
  128. 128. Focus The result of the focus update was determined from the following preferred focus search: | | Starting preferred focus search: | |--> Searching <UIFocusSystem 0x60000028dc00>... | |--> Searching <UIScreen 0x6080001d3fb0>... | |--> Searching <UIWindow 0x7fb79cb02af0>... | |--> Searching <tvos_sample_for_iosdc.RootViewController 0x7fb79c904da0>... | |--> Searching <UIView Focus Update Logging
  129. 129. Focus po UIFocusDebugger.status() <UIButton 0x7f97bac05b90> is currently focused. UIFocusDebugger
  130. 130. Focus po UIFocusDebugger.simulateFocusUpdateRequest(from: imageView) Simulating a fake focus update request from <UIImageView 0x7ff3ce2106d0>... (<tvos_sample_for_iosdc.MainCollectionViewCell 0x7ff3ce20fe60> is currently focused) The following issues were found that would normally prevent this environment's request from being accepted by the focus system (these will be ignored for the purposes of this test): - ISSUE: This environment does not contain the currently focused item. Starting preferred focus search: |--> Searching <UIImageView 0x7ff3ce2106d0>... No more preferences for this environment, and there are no focusable items in this environment to prefer by default. This environment does not prefer a valid focusable item, nor any other environments. Simulated Result: Successfully updated focus to nil. UIFocusDebugger
  131. 131. Focus po UIFocusDebugger.checkFocusability(for: label) The following issues were found that would prevent this item from being focusable: - ISSUE: This view has isUserInteractionEnabled set to NO. Views must allow user interaction to be focusable. UIFocusDebugger
  132. 132. Conclusion
  133. 133. Conclusion • iOSとの違いはFocus • 標準のUI/UXに準拠しよう • tvOS対応は難しくない
  134. 134. Thank you 参考資料 https://developer.apple.com/videos/play/wwdc2017/209/ https://developer.apple.com/videos/play/wwdc2017/224 https://developer.apple.com/tvos/resources/

×