ããã«ã¡ã¯ãï¼æã«å ¥ç¤¾ããiOSã¨ã³ã¸ãã¢ã®ä¸æ(@nkmrh)ã§ãã æ±äº¬ãããããæ¢ é¨ãæãã¦å¤ããã£ã¦ãã¾ããã ãã¦ãå æã¯ WWDC 2020 ããªã³ã©ã¤ã³ã§éå¬ããã¾ãããSwiftUI ã®æ°æ©è½ãçºè¡¨ããããããã宿¦æå ¥ã®æ°éãé«ã¾ã£ã¦ãã¦ããã®ã§ã¯ãªãã§ããããï¼
以ä¸ã®ï¼ã¤ã®ã»ãã·ã§ã³ã§ SwiftUI ã®æ°æ©è½ãç´¹ä»ããã¦ãã¾ããã®ã§ãæ¬ç¨¿ã§ã¯ãããã®ã»ãã·ã§ã³ã§ãç¹ã«ãã¤ã³ãã¨ãªããããªé ç®ãããã¯ã¢ãããã¦ãç´¹ä»ãããã¨æãã¾ãã
Data Essentials in SwiftUI
ãã®ã»ãã·ã§ã³ã§ã¯ããã¥ã¼ã¨ãã¼ã¿ã®ãã¤ã³ãã®æ¹æ³ã«ã¤ãã¦èª¬æããã¦ãã¾ããã æ°ãã追å ãããæ©è½ã®ä¸ã«ä»¥ä¸ã®ãã®ãããã¾ããã
- Property Wrappers
@StateObject
@SceneStorage
@AppStorage
- Modifier
onChange
é çªã«è¦ã¦ããã¾ãããã
@StateObject
class Store: ObservableObject { @Published var count = 0 } struct ParentView: View { @StateObject private var store = Store() var body: some View { ChildView() } }
ä¸è¨ã®ã³ã¼ã㯠@StateObject
ã®ä½¿ç¨ä¾ã§ããã¯ããã« ParentView
ã® body
ã¡ã½ãããå¼ã°ããåã« store
ããããã£ãã¤ã³ã¹ã¿ã³ã¹åããã¾ããï¼ParentView
ãã¤ã³ã¹ã¿ã³ã¹åãããã¿ã¤ãã³ã°ã§ã¯ãªãï¼ããã以é ParentView
ãåã¤ã³ã¹ã¿ã³ã¹åãããå ´åã§ããstore
ããããã£ã®ç¶æ
ã¯ä¿æããç¶ãã¾ãã
@ObservedObject
ã使ç¨ã㦠Store
ãªãã¸ã§ã¯ãã ParentView
ã«ãã¤ã³ãããå ´åãParentView
ãåã¤ã³ã¹ã¿ã³ã¹åãããã¿ã¤ãã³ã°ã§ Store
ãªãã¸ã§ã¯ããåæåããã¦ãã¾ãçºãç¶æ
ãä¿æãã¦ããã«ã¯ Store
ãªãã¸ã§ã¯ããå¤ããæ³¨å
¥ãããå¿
è¦ãããã¾ããã
ã¾ãã@ObservedObject
㯠ParentView
ãåã¤ã³ã¹ã¿ã³ã¹åããã度ã«ã¤ã³ã¹ã¿ã³ã¹åããããã¼ãã¡ã¢ãªãå§è¿«ãããã©ã¼ãã³ã¹ã®æªååå ã¨ãªãçºã@StateObject
ã使ç¨ãããã¨ãæ¨å¥¨ããã¦ãã¾ããã@StateObject
ã®ã©ã¤ããµã¤ã¯ã«ã¯ SwiftUI ãèªåçã«ç®¡çãã¦ãããããã§ãã
æç« ã§ã®èª¬æã ã¨åããã¥ããã¨æãã¾ãã®ã§ããµã³ãã«ã³ã¼ãã§ @StateObject
㨠@ObservedObject
ãå©ç¨ããå ´åã§ã®æåã®éãã確èªãã¦ã¿ã¦ä¸ããã
@SceneStorage
@SceneStorage("selection") var selection: String?
@SceneStorage
ã使ã㨠Scene
åä½ã§ãã¼ã¿ãæ°¸ç¶åã§ãã¾ãã @State
ããããã£ã®ããã« View ã«ãã¤ã³ããã¦ä½¿ãã¾ããScene
åä½ãªã®ã§ãä¿åããããã¼ã¿ã¯ Scene éã§å
±æããã¾ããã å
é¨çã« UserDefaults
ã¯ä½¿ããã¦ããªãããã§ããã»ãã·ã§ã³å
ã§ã¯ Scene-Wide Source of Truth
ã¨ç´¹ä»ããã¦ãã¾ããã
@AppStorage
@AppStorage("updateArtwork") private var updateArtwork = true
@AppStorage
ã¯ããã¾ã§ã® UserDefaults
ã¨åãã§ããUserDefaults
ã View ã«ãã¤ã³ãã§ããããã«ãªã£ãã®ã§ä¾¿å©ããã§ããã
onChange modifier
struct ContentView: View { @State var count = 0 var body: some View { VStack { Button("Increment count") { count += 1 } Text("count \(count)") .onChange(of: count) { newCount in print(newCount) } } } }
onChange
modifier ã使ç¨ãã㨠@State
ããããã£çã®å¤ã®å¤åãç£è¦ãããã¨ãã§ãã¾ãã
以ä¸ã Data Essentials in SwiftUI ã»ãã·ã§ã³ã®ä¸ãããã£ããã¢ãããã¦ããããå 容ã ã¨æãã¾ãã
App Essentials in SwiftUI
ãã®ã»ãã·ã§ã³ã§ã¯ SwiftUI ã«ãããæ°ããã¢ããªã®ã©ã¤ããµã¤ã¯ã«ã®æ¸ãæ¹ãç´¹ä»ããã¦ãã¾ããã
Xcode12以éãã SwiftUI ã¢ããªã±ã¼ã·ã§ã³ãæ°è¦ä½æããã¨ãæ°è¦ä½æãã¤ã¢ãã°ã® Life Cycle
ã®é
ç®ãã SwiftUI App
㨠UIKit App Delegate
ã®ã©ã¡ããã鏿ã§ããããã«ãªã£ã¦ãããå¾è
ã¯å¾æ¥ã® AppDelegate
㨠SceneDelegate
ã使ç¨ãããã¤ã©ã¼ãã¬ã¼ãã§ãView ã表示ããçºã« UIHostingController
ã使ãã¾ãããåè
㯠SwiftUI ã®ã³ã¼ãã ãã§ä½æããã¾ãã
次ã®ã³ã¼ã㯠UIKit App Delegate
鏿æã«çæããã徿¥ã®ãã¤ã©ã¼ãã¬ã¼ãã§ããUIHostingController
ã使ã View ã表示ãã¦ãã¾ãã
class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { let contentView = ContentView() if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) window.rootViewController = UIHostingController(rootView: contentView) self.window = window window.makeKeyAndVisible() } }
ããã¦ã次ã®ã³ã¼ã㯠SwiftUI App
鏿æã«ä½æããããã¤ã©ã¼ãã¬ã¼ãã§ãããã£ãã®ï¼è¡ã§é©ãã¾ãããã»ãã·ã§ã³å
ã§ã¯ã"It's 100% functional app" ã¨ç´¹ä»ããã¦ããã®ãå°è±¡çã§ããã
@main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } } }
ä¸è¨ã®ã³ã¼ããè¦ã¦ããã¾ãããã
@main
ã¾ãã¯ããã«ç®ã«ä»ãã®ã @main
ã§ããããã¯ã
@main 屿§ã§ Swift5.3
ã§å°å
¥ããããã®ã§ãããã®å±æ§ã struct
, class
, enumration
ã«é©ç¨ããã¨ãããã°ã©ã ã®ã¨ã³ããªãã¤ã³ããå«ããã¨ã示ãã¾ããé©ç¨ããã«ã¯ main
颿°ãæä¾ããå¿
è¦ããããSwiftUI ã§ã¯ App
ãããã³ã«ã main 颿°ãæä¾ãã¦ãã¾ãã
App ãããã³ã«
次ã«ãApp ãããã³ã«ã§ããApp ãããã³ã«ã¯ã¢ããªã®æ§é ãåä½ã表ãã¿ã¤ãã§ããApp ãããã³ã«ã«æºæ ããã«ã¯ãï¼ã¤ä»¥ä¸ã® Scene
ãè¿ã body
ããããã£ãå®è£
ããå¿
è¦ãããã¾ãã
WindowGroup
WindowGroup
㯠macOS
㨠iPadOS
ã®ãã«ãã¦ã£ã³ãã¦ã«å¯¾å¿ããWindowGroup
以ä¸ã® View é層ããã«ãã¦ã£ã³ãã¦èµ·åæã®ãã³ãã¬ã¼ãã¨ãªãã¾ããiOS
watchOS
tvOS
ã®å ´åã¯ãï¼ã¤ã®ãã«ã¹ã¯ãªã¼ã³ã¦ã£ã³ãã¦ã¨ãªãã¾ããããã«ããããã©ãããã©ã¼ã ãéã£ã¦ãï¼ã¤ã®ã³ã¼ãã§å¯¾å¿ã§ããããã«ãªãã¨è§£èª¬ããã¦ãã¾ããã
App Scene View ã®é¢ä¿
App, Scene, View ã®é¢ä¿ã¯ä»¥ä¸ã®ããã«ãªããWindowGroup
ã Scene ã管çãã¦ããã¾ãã
徿¥ã® Delagete ãããã³ã«ã¸ã®å¯¾å¿æ¹æ³
App
ãããã³ã«ã§å¾æ¥ã® UISceneDelegate
ã UIApplicationDelegate
ã«å¯¾å¿ããã«ã¯ã©ããããè¯ãã®ã§ããããããã®ç¹ã«ã¤ãã¦ã¯ã»ãã·ã§ã³å
ã§ã¯è§£èª¬ããã¦ãã¾ããã§ãããã以ä¸ã®ããã«ãããã¨ã§å¯¾å¿ã§ããããã§ãã
UISceneDelegate
ã«å¯¾å¿ããã«ã¯ãScenePhase åæåã Environment
ããåå¾ããonChange()
ã¡ã½ããã®å¼æ°ã«è¨å®ãããã¨ã§ãScenePhase
ã®å¤ãç£è¦ãããã¨ã§å¯¾å¿ã§ããããã§ããonChange()
ã¡ã½ããã¯ä¸è¿°ã® Data Essentials in SwiftUI ã§ç´¹ä»ããã¦ãã¾ãããã
@main struct MyApp: App { @Environment(\.scenePhase) private var scenePhase var body: some Scene { WindowGroup { ContentView() } .onChange(of: scenePhase) { newScenePhase in switch newScenePhase { case .active, .inactive, .background: print(newScenePhase) default: fatalError() } } } }
â» Xcode beta2 ã®æç¹ã§ã¯ãã¾ã beta ã®çºãªã®ã background ããå¼ã°ãã¦ããªãããã§ãã
UIApplicationDelegate
ã«å¯¾å¿ããã«ã¯ UIApplicationDelegateAdaptor PropertyWrappers ã使ãã¾ããåæåæã« UIApplicationDelegate
ã«æºæ ããåãæ¸¡ãã¨ãããªã²ã¼ãã¡ã½ãããå¼ã°ããããã«ãªãã¾ãã
@main struct MyApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate ... } final class AppDelegate: NSObject, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { print(#function) return true } func applicationWillTerminate(_ application: UIApplication) { print(#function) } }
macOS ã®å ´å㯠NSApplicationDelegateAdaptor ãç¨æããã¦ãã¾ã
App Essentials in SwiftUI ã»ãã·ã§ã³ã§ã¯ä¸è¨ã®å 容ã解説ããã¦ãã¾ããã
ã¾ã¨ã
æ¬ç¨¿ã§ã¯ãä¸è¨ï¼ã»ãã·ã§ã³ã®å 容ã解説ãã¾ãããSwiftUI ã使ããã¦ããã«ã¤ãã¦ããã«ãã¦ã£ã³ãã¦å¯¾å¿ã macOS 対å¿çã大äºãªãã¤ã³ãã¨ãªã£ã¦ããã®ããããã¾ãããSwiftUI ããã£ããã¢ãããã¦ããä¸ã§åèã«ãªãã°å¹¸ãã§ãã
ãã¡ãã®è¨äºãèªã¾ã㦠Quipper ã«èå³ããæã¡ããã ããçæ§ããã² Quipper ã«éã³ã«æ¥ã¾ãããï¼ ä»¥ä¸ Wantedly ãã¼ã¸ãããæ°è»½ã«ãé£çµ¡ãã ããï¼ https://www.wantedly.com/companies/quipper/projects