Slide 1

Slide 1 text

!@LJ J04։ൃʹ͓͚Δ ΤϯτϦʔϙΠϯτͷྺ࢙ J045FTU/JHIU

Slide 2

Slide 2 text

.FTXJGU let name = "Takuhiro Muta" let twitter = "417_72ki" let github = "417-72KI" let company = "(redacted)" var products = [ "MockUserDefaults", "MultipartFormDataParser", "BuildConfig.swift", "R2ACConverter", "SSGH", ] var contributing = [ "Danger-Swift", "octokit.swift", "etc..." ]

Slide 3

Slide 3 text

͓඼ॻ͖ w ΤϯτϦʔϙΠϯτͱ͸ w J04։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ w ςετͱΤϯτϦʔϙΠϯτ

Slide 4

Slide 4 text

ΤϯτϦʔϙΠϯτͱ͸

Slide 5

Slide 5 text

ΤϯτϦʔϙΠϯτͱ͸ w ΞϓϦέʔγϣϯ౳ͷϓϩάϥϜΛ࣮ߦ͢Δࡍ࠷ॳʹݺͼग़͞ΕΔॲཧ΍ؔ ਺ͷ͜ͱ w $JOUNBJO w +BWBQVCMJDTUBUJDWPJENBJO 4USJOHBSHT w FUD

Slide 6

Slide 6 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ

Slide 7

Slide 7 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ J04ΞϓϦ։ൃͱΤϯτϦʔϙΠϯτͷมભ ࣌ظ ओͳग़དྷࣄ ݴޠ 'SBNFXPSLT ΤϯτϦʔϙΠϯτ ʙ 0CKFDUJWF$ Ћ 6*,JU NBJON 88%$Ͱ4XJGUൃද 9DPEF4XJGUϦϦʔε 0CKFDUJWF$ Ћ 4XJGU Ћ 6*,JU NBJON "QQ%FMFHBUFTXJGU 88%$Ͱ4XJGU6*ൃද 9DPEF4XJGU6*ϦϦʔε 0CKFDUJWF$ Ћ 4XJGU 6*,JU 4XJGU6* NBJON "QQ%FMFHBUFTXJGU 4DFOF%FMFHBUF 4XJGU6*ϦϦʔε 0CKFDUJWF$ Ћ 4XJGU 6*,JU 4XJGU6* NBJON "QQ%FMFHBUFTXJGU 4DFOF%FMFHBUF "QQTXJGU

Slide 8

Slide 8 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ 0CKFDUJWF$ w NBJON #import #import "AppDelegate.h" int main(int argc, char * argv[]) { NSString * appDelegateClassName; @autoreleasepool { appDelegateClassName = NSStringFromClass([AppDelegate class]); } return UIApplicationMain(argc, argv, nil, appDelegateClassName); }

Slide 9

Slide 9 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ 4XJGU w NBJOTXJGU UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self)) 🙅

Slide 10

Slide 10 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ 4XJGUXJUI6*,JU w "QQ%FMFHBUFTXJGU @UIApplicationMain // deprecated and will be error in Swift 6 final class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Initialize app return true } }

Slide 11

Slide 11 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ !6*"QQMJDBUJPO.BJO w NBJOTXJGUΛ҉໧తʹੜ੒͢Δ w 4XJGUͰඇਪ঑ɺ4XJGUͰഇࢭ༧ఆ UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self)) IUUQTHJUIVCDPNBQQMFTXJGUCMPCGFCBEDFEDGDFBFFEE$)"/(&-0(NE QMBJO-- IUUQTHJUIVCDPNBQQMFTXJGUDPNNJUDDCDDGDBC

Slide 12

Slide 12 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ ༨ஊɿ!6*"QQMJDBUJPO.BJOͷࠟ੻ IUUQTHJUIVCDPNTFBSDI RSFQP"BQQMF'TXJGU6*"QQMJDBUJPO.BJOUZQFDPEF

Slide 13

Slide 13 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ 4XJGUXJUI6*,JU w "QQ%FMFHBUFTXJGU @UIApplicationMain // deprecated and will be error in Swift 6 final class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Initialize app return true } }

Slide 14

Slide 14 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ 4XJGU d XJUI6*,JU w "QQ%FMFHBUFTXJGU @main final class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Initialize app return true } }

Slide 15

Slide 15 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ !NBJO w 4XJGUʹ͓͚ΔΤϯτϦʔϙΠϯτΛࣔ͢BUUSJCVUF w 4XJGUͰ௥Ճ w !NBJO͕෇͍ͨDMBTTTUSVDUFOVN͸QVCMJDTUBUJDGVODNBJO ͷ࣮૷ ͕ඞਢ

Slide 16

Slide 16 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ !NBJO

Slide 17

Slide 17 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ 4XJGU6*Y w "QQ%FMFHBUFTXJGU @UIApplicationMain // deprecated and will be error in Swift 6 final class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Initialize SceneDelegate if needed return true } }

Slide 18

Slide 18 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ 4XJGU6*Y w 4DFOF%FMFHBUFTXJGU final class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } let window = UIWindow(windowScene: windowScene) window.rootViewController = UIHostingController(rootView: RootView()) self.window = window window.makeKeyAndVisible() }

Slide 19

Slide 19 text

J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ 4XJGU6*d w "QQTXJGU @main struct EntrypointSample_SwiftUIApp: App { var body: some Scene { WindowGroup { ContentView() } } }

Slide 20

Slide 20 text

4XJGU6*d J04ΞϓϦ։ൃʹ͓͚ΔΤϯτϦʔϙΠϯτ

Slide 21

Slide 21 text

ςετͱΤϯτϦʔϙΠϯτ

Slide 22

Slide 22 text

ςετͱΤϯτϦʔϙΠϯτ J04ͷςετʹ͓͚Δ՝୊ w J04ͷςετ͸)PTU"QQMJDBUJPO্Ͱ࣮ߦ͞ΕΔ w )PTU"QQMJDBUJPO͕ىಈ͢Δ w ىಈ·Ͱͷ͕࣌ؒϘτϧωοΫʹͳΔ w ىಈ࣌ʹ௨৴΍6TFS%FGBVMUT౳΁ͷॻ͖ࠐΈ౳Λ͍ͯ͠ΔͱɺͦΕ͕ࢥ Θ͵෭࡞༻ΛҾ͖ىͯ͜͠ςετʹӨڹ͢Δ৔߹͕͋Δ

Slide 23

Slide 23 text

ςετͱΤϯτϦʔϙΠϯτ ىಈ·Ͱͷ͕࣌ؒϘτϧωοΫʹͳΔ

Slide 24

Slide 24 text

ςετͱΤϯτϦʔϙΠϯτ εϓϥογϡը໘ͰͷॲཧʹΑΔ෭࡞༻ ྫ w γϛϡϨʔλͰಈ࡞֬ೝ͢Δ ϩάΠϯͨ͠ঢ়ଶ w ಉҰγϛϡϨʔλͰςετ࣮ߦ w γϛϡϨʔλͷ6TFS%FGBVMUTʹ࢒͍ͬͯͨτʔΫϯΛ)PTU"QQMJDBUJPO্ͷ TJOHMFUPOPCKFDU͕र্͍͛Δ w ςετର৅ͷதͰͦͷTJOHMFUPOΛݟΔॲཧ͕τʔΫϯΛ࢖ͬͯॲཧͯ͠͠·͏ w ૝ఆͱҟͳΔ࣮ߦ݁Ռ͕ग़ྗ͞Ε౰֘ςετ͕'BJMFEʹ😱

Slide 25

Slide 25 text

ςετͱΤϯτϦʔϙΠϯτ ରࡦ w #FTU w ϓϩμΫτίʔυΛ4XJGU1BDLBHFʹ͢Δ w 1BDLBHFଆͰςετΛ૸ΒͤΔͱ)PTU"QQMJDBUJPOΛ࢖Θͳ͍ w YDGSBNFXPSLඇରԠϥΠϒϥϦ͕͋ͬͨΓ͢ΔͱෆՄ w #FUUFS w "QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ w ىಈॲཧΛεΩοϓͰ͖Δ w /PU#BE w ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"]ͷ༗ແͰ൑அ͢Δ w ϓϩμΫτίʔυ͕ԚΕΔ

Slide 26

Slide 26 text

"QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ w ςετλʔήοτ಺ʹ.PDL"QQ%FMFHBUFΛ༻ҙ͢Δ w "QQ%FMFHBUF͔Β@mainΛফ͢ w NBJOTXJGUΛ༻ҙ͢Δ w ςετ࣌͸.PDL"QQ%FMFHBUFΛݟΔΑ͏ʹࡉ޻͢Δ

Slide 27

Slide 27 text

"QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ ςετλʔήοτ಺ʹ.PDL"QQ%FMFHBUFΛ༻ҙ͢Δ import UIKit @objc(MockAppDelegate) final class MockAppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { print("This is MockAppDelegate") return true } }

Slide 28

Slide 28 text

"QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ w ςετλʔήοτ಺ʹ.PDL"QQ%FMFHBUFΛ༻ҙ͢Δ w "QQ%FMFHBUF͔Β@mainΛফ͢ w NBJOTXJGUΛ༻ҙ͢Δ w ςετ࣌͸.PDL"QQ%FMFHBUFΛݟΔΑ͏ʹࡉ޻͢Δ

Slide 29

Slide 29 text

"QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ "QQ%FMFHBUF͔Β!NBJOΛফ͢ @main final class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { print("This is AppDelegate") return true } ɾ ɾ ɾ

Slide 30

Slide 30 text

"QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ "QQ%FMFHBUF͔Β!NBJOΛফ͢ final class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { print("This is AppDelegate") return true } ɾ ɾ ɾ

Slide 31

Slide 31 text

"QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ w ςετλʔήοτ಺ʹ.PDL"QQ%FMFHBUFΛ༻ҙ͢Δ w "QQ%FMFHBUF͔Β@mainΛফ͢ w NBJOTXJGUΛ༻ҙ͢Δ w ςετ࣌͸.PDL"QQ%FMFHBUFΛݟΔΑ͏ʹࡉ޻͢Δ

Slide 32

Slide 32 text

"QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ NBJOTXJGUΛ༻ҙͯ͠ςετ࣌͸.PDL"QQ%FMFHBUFΛݟΔΑ͏ʹࡉ޻͢Δ UIApplicationMain( CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(AppDelegate.self) )

Slide 33

Slide 33 text

"QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ NBJOTXJGUΛ༻ҙͯ͠ςετ࣌͸.PDL"QQ%FMFHBUFΛݟΔΑ͏ʹࡉ޻͢Δ let appDelegateClass: AnyClass = NSClassFromString("MockAppDelegate") ?? AppDelegate.self UIApplicationMain( CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(appDelegateClass) )

Slide 34

Slide 34 text

"QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ

Slide 35

Slide 35 text

"QQ%FMFHBUFΛ࣮ߦ͠ͳ͍Α͏ʹ͢Δ #JUSJTF্Ͱͷςετ࣮ߦ࣌ؒൺֱ ௒ͬ͘͟Γ w #FGPSF w ฏۉ໿N w "GUFS w ฏۉ໿N

Slide 36

Slide 36 text

1VSF4XJGU6*"QQͷ৔߹ .PDL"QQΛ/40CKFDUʹ͢Δ @objc(MockApp) final class MockApp: NSObject, App { override init() { super.init() print("This is MockApp.") } var body: some Scene { WindowGroup { EmptyView() } } }

Slide 37

Slide 37 text

1VSF4XJGU6*"QQͷ৔߹ BOZ"QQ5ZQFͰΩϟετ͢Δ͜ͱͰNBJO ͕ݺͼग़ͤΔ if let clazz = NSClassFromString("MockApp") as? any App.Type { clazz.main() } else { EntrypointSample_SwiftUIApp.main() }

Slide 38

Slide 38 text

·ͱΊ

Slide 39

Slide 39 text

·ͱΊ w J04։ൃͷྺ࢙ͷதͰΤϯτϦʔϙΠϯτ͸ෳ਺ճมΘ͍ͬͯΔ w ΤϯτϦʔϙΠϯτͱࠇຐज़Λ࢖ͬͯςετ࣌ͷ)PTU"QQMJDBUJPOͷىಈॲ ཧΛճආͰ͖Δ w ςετͷ࣮ߦ͕࣌ؒ୹ॖͰ͖Δ w αϯϓϧίʔυ w IUUQTHJUIVCDPN,*&OUSZQPJOU4BNQMF

Slide 40

Slide 40 text

'JO