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

iPadOSDC: Multiple Windows

Hiron
September 20, 2020

iPadOSDC: Multiple Windows

iOSDC Japan 2020の発表資料です。
スライド中のApple公式資料へのリンクは https://gist.github.com/hironytic/67757d4275e3b19509d892080d78b38c も参照

Hiron

September 20, 2020
Tweet

More Decks by Hiron

Other Decks in Programming

Transcript

  1. J1BE04 5JNF   "QSJM  +VOF  J1IPOF04 J1IPOF04

    J04 J04 J1BE04 J1BE .VMUJUBTLJOH .VMUJQMF 8JOEPXT
  2. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX

    7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF 6*4DFOF /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ
  3. *OGPQMJTUʹ4DFOF.BOJGFTUΛ௥Ճ <key>UIApplicationSceneManifest</key> <dict> <key>UIApplicationSupportsMultipleScenes</key> <false/> <key>UISceneConfigurations</key> <dict> <key>UIWindowSceneSessionRoleApplication</key> <array> <dict>

    <key>UISceneConfigurationName</key> <string>Default Configuration</string> <key>UISceneDelegateClassName</key> <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string> <key>UISceneStoryboardFile</key> <string>Main</string> </dict> </array> </dict> </dict> ˡ1SPQFSUZ-JTUදࣔ 4PVSDF$PEFදࣔˠ
  4. "QQ%FMFHBUFʹϝιουΛ଍͢ class AppDelegate: UIResponder, UIApplicationDelegate { ... func application(_ application:

    UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // Called when a new scene session is being created. // Use this method to select a configuration to create the new scene with. return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } ... }
  5. 4DFOF%FMFHBUFΫϥεΛ࡞Δ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func

    scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the // UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically // be initialized and attached to the scene. // This delegate does not imply the connecting scene or session are // new (see `application:configurationForConnectingSceneSession` instead). guard let _ = (scene as? UIWindowScene) else { return } } func sceneDidDisconnect(_ scene: UIScene) { ...
  6. 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ొ৔ਓ෺૬ؔਤ 6*8JOEPX 7JFX$POUSPMMFS

    6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF 6*4DFOF /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੵΉ "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*"QQMJDBUJPO
  7. 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF ΫϥεΛࢦఆ ొ৔ਓ෺૬ؔਤ 6*8JOEPX 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX

    6*8JOEPX4DFOF 6*4DFOF /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੵΉ "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO ੜ੒ͯ͠ฦ͢ 6*"QQMJDBUJPO
  8. ొ৔ਓ෺૬ؔਤ 6*8JOEPX 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੵΉ

    "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ 6*"QQMJDBUJPO 6*8JOEPX4DFOF 6*4DFOF
  9. ొ৔ਓ෺૬ؔਤ /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੵΉ "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF

    6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ 6*8JOEPX 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX 6*"QQMJDBUJPO 6*8JOEPX4DFOF 6*4DFOF
  10. 4DFOF%FMFHBUF "QQ%FMFHBUFͷҎԼͷϝιου͸ݺ͹Εͳ͘ͳΔ  BQQMJDBUJPO%JE#FDPNF"DUJWF @   BQQMJDBUJPO8JMM3FTJHO"DUJWF @ 

     BQQMJDBUJPO%JE&OUFS#BDLHSPVOE @   BQQMJDBUJPO8JMM&OUFS'PSFHSPVOE @   ͳͲ 4DFOF%FMFHBUFͷҎԼͷϝιου͕ݺ͹ΕΔΑ͏ʹͳΔ  TDFOF%JE#FDPNF"DUJWF @   TDFOF8JMM3FTJHO"DUJWF @   TDFOF%JE&OUFS#BDLHSPVOE @   TDFOF8JMM&OUFS'PSFHSPVOE @   ͳͲ ˞J04Ͱ͸ݺ͹ΕΔ
  11. 4DFOF%FMFHBUF "QQ%FMFHBUFͷ BQQMJDBUJPO @EJE'JOJTI-BVODIJOH8JUI0QUJPOT ͸ݺ͹ΕΔ͕ɺ ΢Οϯυ΢ͷߏஙͳͲ͸4DFOF%FMFHBUFͷ TDFOF @XJMM$POOFDU5PPQUJPOT Ͱߦ͏ func

    scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the // UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically // be initialized and attached to the scene. // This delegate does not imply the connecting scene or session are // new (see `application:configurationForConnectingSceneSession` instead). guard let _ = (scene as? UIWindowScene) else { return } }
  12. "QQ%FMFHBUF͔Β4DFOF%FMFHBUF΁Ҿͬӽ͠ func applicationWillResignActive(_ application: UIApplication) { // Sent when the

    application is about to move from active to inactive state. // This can occur for certain types of temporary interruptions (such as an // incoming phone call or SMS message) or when the user quits the application // and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and invalidate // graphics rendering callbacks. Games should use this method to pause the game. } func applicationDidEnterBackground(_ application: UIApplication) { // Use this method to release shared resources, save user data, invalidate // timers, and store enough application state information to restore your // application to its current state in case it is terminated later. // If your application supports background execution, this method is called // instead of applicationWillTerminate: when the user quits. } func applicationWillEnterForeground(_ application: UIApplication) { ... var window: UIWindow?
  13. *OGPQMJTUͷ4DFOF.BOJGFTUΛมߋ <key>UIApplicationSceneManifest</key> <dict> <key>UIApplicationSupportsMultipleScenes</key> <true/> <key>UISceneConfigurations</key> <dict> <key>UIWindowSceneSessionRoleApplication</key> <array> <dict>

    <key>UISceneConfigurationName</key> <string>Default Configuration</string> <key>UISceneDelegateClassName</key> <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string> <key>UISceneStoryboardFile</key> <string>Main</string> </dict> </array> </dict> </dict> ˡ1SPQFSUZ-JTUදࣔ 4PVSDF$PEFදࣔˠ
  14. /46TFS"DUJWJUZ w ΞϓϦͷঢ়ଶΛදݱ͢ΔΫϥε w .VMUJQMF8JOEPXTҎ֎Ͱ΋࢖ΘΕΔ  )BOEP⒎ 4JSJ4IPSUDVUT  w

    ΞϓϦݻ༗ͷঢ়ଶΛ֨ೲͰ͖ΔϓϩύςΟ͕͋Δ  ೖΕΒΕΔ΋ͷ /4"SSBZ /4%BUB /4%BUF /4%JDUJPOBSZ /4/VMM /4/VNCFS /44FU /44USJOH /463- var userInfo: [AnyHashable : Any]? { get set }
  15. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX

    7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF 6*4DFOF /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ /46TFS"DUJWJUZ
  16. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 6*8JOEPX 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF

    6*4DFOF /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ /46TFS"DUJWJUZ 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF
  17. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 6*8JOEPX 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX /4*UFN1SPWJEFS

    6*%SBH*UFN 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ /46TFS"DUJWJUZ 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX4DFOF 6*4DFOF
  18. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 6*8JOEPX 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX /4*UFN1SPWJEFS

    6*%SBH*UFN 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ /46TFS"DUJWJUZ 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX4DFOF 6*4DFOF VTFS"DUJWJUZ
  19. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ

    ੵΉ /46TFS"DUJWJUZ 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX4DFOF 6*4DFOF VTFS"DUJWJUZ 6*8JOEPX 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX XJOEPX4DFOF XJOEPX WJFX
  20. 6*4DFOFʹ/46TFS"DUJWJUZΛηοτ override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let userActivity

    = NSUserActivity(activityType: "com.hironytic.Sessions.SessionDetail") userActivity.userInfo = [ "sessionId": sessionId ] view.window?.windowScene?.userActivity = userActivity } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) view.window?.windowScene?.userActivity = nil ... } 4FTTJPO%FUBJM7JFX$POUSPMMFSʢৄࡉը໘ʣ 4FTTJPO-JTU7JFX$POUSPMMFSʢҰཡը໘ʣ
  21. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 6*8JOEPX 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF

    6*4DFOF /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF
  22. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 6*8JOEPX 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF

    6*4DFOF /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*%SBH*UFN ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*4DFOF4FTTJPO
  23. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 6*8JOEPX 7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF

    6*4DFOF /4*UFN1SPWJEFS 6*%SBH*UFN ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*4DFOF4FTTJPO /46TFS"DUJWJUZ TUBUF3FTUPSBUJPO"DUJWJUZ
  24. ঢ়ଶͷ෮ݩ func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions:

    UIScene.ConnectionOptions) { ... if let activity = session.stateRestorationActivity { setupViewController(with: activity) } } func setupViewController(with activity: NSUserActivity) { guard activity.activityType == "com.hironytic.Sessions.SessionDetail" else { return } guard let sessionId = activity.userInfo?["sessionId"] as? String else { return } guard let navigationController = window?.rootViewController as? UINavigationController else { return } let detailVc = SessionDetailViewController.instantiate(sessionId: sessionId) navigationController.pushViewController(detailVc, animated: false) } 4DFOF%FMFHBUF
  25. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX

    7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF 6*4DFOF /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ 6*%SBH*UFN
  26. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX

    7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF 6*4DFOF /46TFS"DUJWJUZ 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ 6*%SBH*UFN /4*UFN1SPWJEFS
  27. ొ৔ਓ෺૬ؔਤ 6*"QQMJDBUJPO "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX

    7JFX$POUSPMMFS 6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF 6*4DFOF 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ 6*%SBH*UFN /4*UFN1SPWJEFS /46TFS"DUJWJUZ /4*UFN1SPWJEFS8SJUJOH ੵΉ
  28. υϥοάͷ։࢝ class SessionListViewController: UITableViewController { ... override func viewDidLoad() {

    super.viewDidLoad() tableView.dragDelegate = self ... } ... } extension SessionListViewController: UITableViewDragDelegate { func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { let session = sessions[indexPath.row] let userActivity = NSUserActivity(activityType: "com.hironytic.Sessions.SessionDetail") userActivity.userInfo = [ "sessionId": session.id ] let itemProvider = NSItemProvider(object: userActivity) let dragItem = UIDragItem(itemProvider: itemProvider) return [dragItem] } } 4FTTJPO-JTU7JFX$POUSPMMFSʢҰཡը໘ʣ
  29. /46TFS"DUJWJUZͷड͚औΓ func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions:

    UIScene.ConnectionOptions) { ... if let activity = connectionOptions.userActivities.first ?? session.stateRestorationActivity { setupViewController(with: activity) } } 4DFOF%FMFHBUF
  30. )*(ʹ΋ॻ͔Ε͍ͯΔ Use a Done or Close button in an auxiliary

    window. When a primary window displays a document, the window typically includes a Back button that lets people navigate to a parent view. In contrast, when an auxiliary window displays a document, the Back button should be replaced with a Done or Close button, because people expect to close an auxiliary window when they're finished working in it. IUUQTEFWFMPQFSBQQMFDPNEFTJHOIVNBOJOUFSGBDFHVJEFMJOFTJPTTZTUFNDBQBCJMJUJFTNVMUJQMFXJOEPXT
  31. /46TFS"DUJWJUZʹϑϥάΛ࣋ͨͤΔ extension SessionListViewController: UITableViewDragDelegate { func tableView(_ tableView: UITableView, itemsForBeginning

    session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] { let session = sessions[indexPath.row] let userActivity = NSUserActivity(activityType: "com.hironytic.Sessions.SessionDetail") userActivity.userInfo = [ "sessionId": session.id, "isAuxiliary": true, ] let itemProvider = NSItemProvider(object: userActivity) let dragItem = UIDragItem(itemProvider: itemProvider) return [dragItem] } } 4FTTJPO-JTU7JFX$POUSPMMFSʢҰཡը໘ʣ
  32. ৄࡉը໘ͷ7JFX$POUSPMMFS·ͰҾ͖౉͢ func setupViewController(with activity: NSUserActivity) { guard activity.activityType == "com.hironytic.Sessions.SessionDetail"

    else { return } guard let sessionId = activity.userInfo?["sessionId"] as? String else { return } guard let navigationController = window?.rootViewController as? UINavigationController else { return } let isAuxiliary = activity.userInfo?["isAuxiliary"] as? Bool ?? false let detailVc = SessionDetailViewController.instantiate(sessionId: sessionId, isAuxiliary: isAuxiliary) navigationController.pushViewController(detailVc, animated: false) } 4DFOF%FMFHBUF
  33. ϑϥάΛݟͯࠨ্ͷϘλϯΛมߋ override func viewDidLoad() { super.viewDidLoad() if isAuxiliary { let

    closeItem = UIBarButtonItem(title: "Close", style: .plain, target: self, action: #selector(closeButtonDidTap(_:))) navigationItem.leftBarButtonItem = closeItem } ... } 4FTTJPO%FUBJM7JFX$POUSPMMFSʢৄࡉը໘ʣ override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let userActivity = NSUserActivity(activityType: "com.hironytic.Sessions.SessionDetail") userActivity.userInfo = [ "sessionId": sessionId, "isAuxiliary": isAuxiliary, ] view.window?.windowScene?.userActivity = userActivity } ঢ়ଶอଘͷํʹ΋ ϑϥάΛ௥Ճɹˠ
  34. $MPTFϘλϯͷॲཧ @objc private func closeButtonDidTap(_ sender: Any) { guard let

    scene = view.window?.windowScene else { return } let options = UIWindowSceneDestructionRequestOptions() options.windowDismissalAnimation = .standard UIApplication.shared .requestSceneSessionDestruction(scene.session, options: options) } 4FTTJPO%FUBJM7JFX$POUSPMMFSʢৄࡉը໘ʣ
  35. γʔϯͷϥΠϑαΠΫϧ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOVJLJUBQQ@BOE@FOWJSPONFOUNBOBHJOH@ZPVS@BQQ@T@MJGF@DZDMF TDFOF @XJMM$POOFDU5PPQUJPOT TDFOF8JMM&OUFS'PSFHSPVOE @ TDFOF%JE#FDPNF"DUJWF @ TDFOF8JMM3FTJHO"DUJWF @

    TDFOF%JE&OUFS#BDLHSPVOE @ TDFOF%JE%JTDPOOFDU @ Discarded γʔϯ͕ด͡ΒΕͨͱ͖ BQQMJDBUJPO @EJE%JTDBSE4DFOF4FTTJPOT "QQεΠονϟʔ͔Βดͨ͡ͱ͖͸ ʮดͨ͡΢Οϯυ΢Λ࠶ͼ։͘ʯ͕ ༗ޮͳ࣌఺Ͱ͸·ͩݺ͹Εͳ͍
  36. ొ৔ਓ෺૬ؔਤ "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX 7JFX$POUSPMMFS

    6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF 6*4DFOF /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ 6*"QQMJDBUJPO
  37. ొ৔ਓ෺૬ؔਤ "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX 7JFX$POUSPMMFS

    6*7JFX$POUSPMMFS 7JFX /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*%SBH*UFN 6*4DFOF4FTTJPO ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ 6*"QQMJDBUJPO 6*8JOEPX4DFOF 6*4DFOF DPOOFDUFE4DFOFT
  38. ొ৔ਓ෺૬ؔਤ "QQ%FMFHBUF 6*"QQMJDBUJPO%FMFHBUF 6*4DFOF$POpHVSBUJPO 4DFOF%FMFHBUF 6*8JOEPX4DFOF%FMFHBUF  6*4DFOF%FMFHBUF 6*8JOEPX 7JFX$POUSPMMFS

    6*7JFX$POUSPMMFS 7JFX 6*8JOEPX4DFOF 6*4DFOF /46TFS"DUJWJUZ /4*UFN1SPWJEFS 6*%SBH*UFN ੜ੒ͯ͠ฦ͢ ΫϥεΛࢦఆ ੵΉ 6*"QQMJDBUJPO 6*4DFOF4FTTJPO PQFO4FTTJPOT
  39. "DUJWBUJPO$POEJUJPOT w 6*4DFOFͷϓϩύςΟ BDUJWBUJPO$POEJUJPOT  w /41SFEJDBUFͷϓϩύςΟΛͭ࣋ͭ  DBO"DUJWBUF'PS5BSHFU$POUFOU*EFOUJpFS1SFEJDBUF 

    QSFGFST5P"DUJWBUF'PS5BSHFU$POUFOU*EFOUJpFS1SFEJDBUF activationConditions.prefersToActivateForTargetContentIdentifierPredicate = NSPredicate(format: "self == %@", "com.hironytic.Sessions.SessionDetail/\(sessionId)")
  40. 3FDBQ w .VMUJQMF8JOEPXTͱ͸Ͳ͏͍͏΋ͷ͔  ඪ४ʮϝϞʯΞϓϦΛྫʹͯ͠ղઆ w .VMUJQMF8JOEPXT΁ͷରԠํ๏  γʔϯ"1*ʹରԠͯ͠&OBCMFʹ͢Δ 

    γʔϯͷঢ়ଶอଘ  υϥοάʹΑΔ৽͍͠γʔϯͷ࡞੒ w ͦͷଞͷτϐοΫ  ϥΠϑαΠΫϧ  ঢ়ଶͷಉظ  ద੾ͳγʔϯͷબ୒
  41. ͓·͚ɿ"QQMFެࣜࢿྉ w 88%$*OUSPEVDJOH.VMUJQMF8JOEPXTPOJ1BE IUUQTEFWFMPQFSBQQMFDPNXXED w 88%$"SDIJUFDUJOH:PVS"QQGPS.VMUJQMF8JOEPXT IUUQTEFWFMPQFSBQQMFDPNXXED w 88%$5BSHFUJOH$POUFOUXJUI.VMUJQMF8JOEPXT IUUQTEFWFMPQFSBQQMFDPNXXED

    w %PDVNFOUBUJPO6*,JU"QQBOE&OWJSPONFOU4DFOFT IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOVJLJUBQQ@BOE@FOWJSPONFOUTDFOFT w )VNBO*OUFSGBDF(VJEFMJOF.VMUJQMF8JOEPXTPOJ1BE IUUQTEFWFMPQFSBQQMFDPNEFTJHOIVNBOJOUFSGBDFHVJEFMJOFTJPTTZTUFNDBQBCJMJUJFTNVMUJQMF XJOEPXT w 4VQQPSUJOH.VMUJQMF8JOEPXTPOJ1BEʢαϯϓϧίʔυʣ IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPOVJLJUBQQ@BOE@FOWJSPONFOUTDFOFT TVQQPSUJOH@NVMUJQMF@XJOEPXT@PO@JQBE
  42. ͓·͚ɿ9DPEFͰ৽نϓϩδΣΫτ࡞੒௚ޙ ʹɺJ04Λαϙʔτ͢Δํ๏ w %FQMPZNFOU5BSHFUΛมߋ͢Δ w 4DFOF%FMFHBUFʹJ04Ҏ߱ͷଐੑΛ͚ͭΔ w "QQ%FMFHBUFʹXJOEPXϓϩύςΟΛੜ΍͢ w "QQ%FMFHBUFͷγʔϯབྷΈͷϝιουʹJ04Ҏ߱ͷଐੑΛͭ

    ͚Δ @available(iOS 13.0, *) class SceneDelegate: UIResponder, UIWindowSceneDelegate { ... @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? ... @available(iOS 13.0, *) func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {...} @available(iOS 13.0, *) func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {...}