I’m following the iOS Turbo Native guides that are found here
Just trying to connect up their exact example for the button, to ensure there is a proper connection going. It’s not working yet, one thing I’m noticing is when my Stimulus controller inherits from BridgeComponent that I don’t see initialize or connect events happening. I’m curious if this is normal, or if that in indicating where my problem is.
In either case this is roughly my setup.
Backend
Rails 7.2
app/javascript/controllers/application.js
I’ve enabled debugging here so I can see all the events.
import { Application } from "@hotwired/stimulus"
const application = Application.start()
// Configure Stimulus development experience
application.debug = true
window.Stimulus = application
export { application }
app/javascript/controllers/bridge/button_controller.js
Then I have the bridge javascript component
import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
export default class extends BridgeComponent {
static component = "button"
connect() {
console.log("bridge button connected")
super.connect()
const element = this.bridgeElement
const title = element.bridgeAttribute("title")
this.send("connect", {title}, () => {
this.element.click()
})
}
}
app/views/layouts/application.html.erb
I’m connecting it up to my button in my main layout.
<button type="button" data-controller="bridge--button" data-bridge-title="Profile">
iOS
ButtonComponent.swift
I added the ButtonComponent using code from here
import HotwireNative
import UIKit
final class ButtonComponent: BridgeComponent {
override class var name: String { "button" }
override func onReceive(message: Message) {
guard let viewController else { return }
addButton(via: message, to: viewController)
}
private var viewController: UIViewController? {
delegate.destination as? UIViewController
}
private func addButton(via message: Message, to viewController: UIViewController) {
guard let data: MessageData = message.data() else { return }
let action = UIAction { [unowned self] _ in
self.reply(to: "connect")
}
let item = UIBarButtonItem(title: data.title, primaryAction: action)
viewController.navigationItem.rightBarButtonItem = item
}
}
private extension ButtonComponent {
struct MessageData: Decodable {
let title: String
}
}
SceneDelegate.swift
And then linked it up in the SceneDeletegate
import HotwireNative
import UIKit
let rootURL = URL(string: "https://my.domain")!
let localPathConfigURL = Bundle.main.url(forResource: "path-configuration", withExtension: "json")!
let pathConfiguration = PathConfiguration(sources: [
.file(localPathConfigURL),
])
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
private let navigator = Navigator(pathConfiguration: pathConfiguration)
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
window?.rootViewController = navigator.rootViewController
Hotwire.registerBridgeComponents([
ButtonComponent.self
])
navigator.route(rootURL)
}
}
Output
Starting it up I’m noticing three clear things.
- There is no button rendered in the iOS app
- The stimulus debugging doesn’t show initialized or connected for the bridge–button controller.
- The javascript console doesn’t show my console.log when connecting.
Now what’s interesting is I can swap out BridgeComponent in the JavaScript with the typical stimulus Controller and I start to see events. (Of course the button still doesn’t show, but I’m sure that’s because that controller doesn’t know how to connect.)
I thought maybe I don’t have recent versions of the javascript dependencies, but I believe I’m pretty much up to date.
- turbo-rails 8.0.10
- stimulus 3.2.2
- hotwire-native-bridge 1.0.0
Is there anything I’m missing here?