@Tutorial(time: 30) { @Intro(title: "Build your first iOS app on Linux / Windows") { Once you've completed , use xtool to build and deploy an iOS app from your Linux/Windows machine. } @Section(title: "Create an xtool project") { We'll start by creating a project from xtool's default template. @Steps { @Step { xtool comes with a template for iOS-capable Swift Packages. Run `xtool new` to create a new package. @Code(name: "Terminal", file: "template-1b.sh", previousFile: "template-1a.sh") {} } @Step { At this point, feel free to poke around. Observe that the package is structured a lot like a regular SwiftPM library, with a few extra files. @Code(name: "Terminal", file: "template-2b.sh", previousFile: "template-2a.sh") {} } @Step { Read `xtool.yml`. This file describes how to bundle the Swift library into an iOS app. At minimum, you need to provide a Bundle ID. This defaults to `com.example.`, in this case `com.example.Hello`. @Code(name: "Terminal", file: "template-3b.sh", previousFile: "template-3a.sh") {} } @Step { Read `.bsp/xtool.json`. This file tells your IDE to ask xtool for build information (via the Build Server Protocol). It enables features like syntax highlighting and documentation lookup. @Code(name: "Terminal", file: "template-4b.sh", previousFile: "template-4a.sh") {} } } } @Section(title: "Build and run") { Now that we have a skeleton project, let's get it running on your device. @Steps { @Step { From inside the package directory, run `xtool dev`. The first time you run this, SwiftPM might take a few minutes to build the app. This is because it needs to build the Swift Modules for the iOS SDK. Subsequent runs should be a lot faster since SwiftPM caches these modules globally. @Code(name: "Terminal", file: "build-1b.sh", previousFile: "build-1a.sh") } @Step { After the build is complete, xtool will attempt to install it on your device. At this point, connect your iOS device to your computer via USB. If you installed `libimobiledevice-utils` during setup, you can verify that your device is connected by running `ideviceinfo`. xtool will continue after automatically detecting that your device is connected. @Code(name: "Terminal", file: "build-2.sh", reset: true) } @Step { Pair your device if prompted. The first time you run `xtool dev`, you may see a "Trust" dialog on your iOS device to proceed with pairing. Tap **Trust** and enter your passcode on iOS. xtool may throw an error after this: if so, just run `xtool dev` again. @Code(name: "Terminal", file: "build-2.sh", reset: true) { @Image(source: "Trust", alt: "Prompt alerting user to trust device") } } @Step { xtool will now connect to Apple Developer Services, register your device with your Apple ID, generate a Certificate + App ID + Provisioning Profile, sign the app, and then install it. @Code(name: "Terminal", file: "build-3.sh", reset: true) {} } @Step { Enable Developer Mode if needed. At this point, you may run into an error asking you to enable **Development Mode** on your iOS device. Follow [these instructions](https://developer.apple.com/documentation/xcode/enabling-developer-mode-on-a-device) and then run `xtool dev` again. @Code(name: "Terminal", file: "build-3.sh", reset: true) { @Image(source: "Developer", alt: "Developer mode in Settings") } } @Step { You should now see the app on your iOS device's home screen / App Library. Tap it to launch the app. @Image(source: "Home", alt: "Hello app on the home screen") } @Step { The first time you launch the app, observe that you may get an "Untrusted Developer" alert. @Image(source: "UntrustedDev", alt: "Alert prompting user to trust certificate") } @Step { Go to **Settings** > **General** > **VPN & Device Management** > _[your email]_ > **Trust**. @Image(source: "Verified", alt: "Trust settings") } @Step { You should now be able to launch the app! @Image(source: "HelloWorld", alt: "Hello world app") } } } @Section(title: "Edit and re-run") { We'll make a small change to the app in your favorite code editor, and then re-run it. @Steps { @Step { Follow the instructions to configure [SourceKit-LSP](https://github.com/swiftlang/sourcekit-lsp/blob/242609dcad55824d9eb23269c0aeead187fd0faa/Documentation/Editor%20Integration.md) for your IDE. For example, if you're using Visual Studio Code, this means you need to install the [Swift extension](https://marketplace.visualstudio.com/items?itemName=swiftlang.swift-vscode). If you're on Windows, make sure you're [connected to the WSL remote](https://code.visualstudio.com/docs/remote/wsl). @Image(source: "SwiftExtension", alt: "Swift extension for VSCode") } @Step { Open the project folder in your editor, and drill down to `Sources/Hello/ContentView.swift`. @Code(name: "ContentView.swift", file: "edit-2.swift") {} } @Step { If you've configured SourceKit-LSP correctly, you should see rich documentation when you hover over the various types and methods. @Code(name: "ContentView.swift", file: "edit-2.swift") { @Image(source: "Hover", alt: "Intellisense") } } @Step { Let's update the "Hello, world!" text to be bold and purple. @Code(name: "ContentView.swift", file: "edit-4.swift") {} } @Step { Run `xtool dev` again to re-build and re-install. This should go a lot faster than the first time. @Code(name: "Terminal", file: "rerun-5b.sh", previousFile: "rerun-5a.sh") {} } @Step { Launch the app again to see the updated text! @Code(name: "Terminal", file: "rerun-6.sh") { @Image(source: "HelloWorld-Purple", alt: "Updated Hello app") } } } } }