Overview
This guide walks you through creating your first iOS app using Hotwire Native, starting from absolute basics. We’ll build a simple bookmarks app that connects to a Rails backend, assuming no prior iOS development experience.
Prerequisites
-
Xcode installed (follow "Setting Up iOS Development Environment" guide)
-
A Rails application with Hotwire enabled
-
Basic understanding of Ruby on Rails
-
macOS computer
Project Setup
Creating a New Xcode Project
-
Open Xcode
-
Click "Create a new Xcode project" (or File → New → Project)
-
Select "App" under iOS templates
-
Configure your project:
Product Name: Bookmarks
Team: Your Name
Organization Identifier: com.example
Interface: Storyboard
Language: Swift
Leave all the checkboxes unchecked and then proceed with the rest of the guide.
PS: It’s okay if you want to use SwiftUI for the views later, we just need select Storyboard to start with so the mobile app will be generated with files we need. We will add custom SwiftUI views later.
|
Tip
|
The Organization Identifier is typically your domain name in reverse. For example, if your website is example.com, use com.example So for our bookmarks app I used |
Adding Dependencies
-
In Xcode, select File → Add Packages
-
Click the '+' button in the top-left corner
-
Enter the Hotwire Native iOS repository URL:
https://github.com/hotwired/hotwire-native-ios
-
Click "Add Package"
Run the app for the first time
Click Product → Run or press Command + R to run the app in the simulator. You should see a blank screen, really riveting stuff! But you now know that your app is set up correctly and ready to be built upon.
Basic App Structure
First in SceneDelegate.swift, delete all the existing content and then import the HotwireNative module and UIKit.
import HotwireNative
import UIKit
Also let’s go ahead and add a variable to hold the rootURL of our Rails app:
let rootURL = URL(string: "http://localhost:3000")!
Note that you should replace http://localhost:3000 with the URL of your Rails app. Also keep in mind the ! at the end of the URL, it’s a force unwrap operator that will crash the app if the URL is not valid.
Next up let’s ensure we setup a window and a navigator in the SceneDelegate class:
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
private let navigator = Navigator()
}
Note that the window var is optional so we mark that with a ? at the end. Also, the navigator is a new instance of the Navigator class we imported from Hotwire Native.
iOS will set the window property for us after things are initialized so it needs to be optional so we can allow the nil value at first.
Next up let’s add the scene function to the SceneDelegate class:
func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) {
window?.rootViewController = navigator.rootViewController
navigator.route(rootURL)
}
We mark the scene parameter as _ because we don’t use it in the function body, just like we would with a variable we don’t use in Ruby.
In order for iOS to actually render content, we have to set the root view controller of the window to the navigator’s root view controller. View Controllers are the building blocks of iOS apps and they are used to manage the content of the app. Think of them like a Rails controller + view combined, it’s really nifty!
Finally, we call the route function on the navigator with the rootURL we defined earlier. This function will load the content from the Rails app and render it in the app.
Now, go ahead and run the app again in the simulator, and if all goes well and you’re running your Rails app locally on port 3000, you should see the content from your Rails app in the iOS app!