Skip to content

Bridged Views in packages #80

@marcprux

Description

@marcprux

It doesn't appear to be possible to provide a module that bridges a transpiled view that can be used from an external package. This is something we will want to do for packages like skip-motion and skip-web so that natively compiled Swift views will be able to utilize these modules in the same way as transpiled view can.

Attempting to bridge a sample view at SkipBridgeViewDemo.swift:

#if !SKIP_BRIDGE
import Foundation
#if canImport(SkipFuseUI)
import SkipFuseUI
#else
import SwiftUI
#endif

/// Example of a view that can be used in a native `SkipFuseUI` app.
public struct SkipBridgedDemoView : View {
    public init() {
    }

    public var body: some View {
        #if SKIP
        ComposeView { ctx in // Mix in Compose code!
            androidx.compose.material3.Text("💚 Hello Android!", modifier: ctx.modifier)
        }
        #else
        Text(verbatim: "💙 Hello Darwin!")
        #endif
    }
}
#endif

This results in the following bridged code SkipBridgeViewDemo_Bridge.swift:

import SkipBridge

import Foundation
import SkipFuseUI
import SkipModel
public struct SkipBridgedDemoView: View, BridgedFromKotlin {
    private static let Java_class = try! JClass(name: "skip/bridged/view/demo/SkipBridgedDemoView")
    public var Java_peer: JObject
    public init(Java_ptr: JavaObjectPointer) {
        Java_peer = JObject(Java_ptr)
    }
    public static func fromJavaObject(_ obj: JavaObjectPointer?, options: JConvertibleOptions) -> Self {
        return .init(Java_ptr: obj!)
    }
    public func toJavaObject(options: JConvertibleOptions) -> JavaObjectPointer? {
        return Java_peer.safePointer()
    }

    public init() {
        Java_peer = jniContext {
            let ptr = try! Self.Java_class.create(ctor: Self.Java_constructor_0_methodID, options: [], args: [])
            return JObject(ptr)
        }
    }
    private static let Java_constructor_0_methodID = Java_class.getMethodID(name: "<init>", sig: "()V")!

    public var body: (some View) {
        get {
            return jniContext {
                let value_java: JavaObjectPointer = try! Java_peer.call(method: Self.Java_get_body_methodID, options: [], args: [])
                return AnyBridging.fromJavaObject(value_java, options: []) { View_BridgeImpl.fromJavaObject(value_java, options: []) as Any } as! (any View)
            }
        }
    }
    private static let Java_get_body_methodID = Java_class.getMethodID(name: "getBody", sig: "()Lskip/ui/View;")!
}
@_cdecl("Java_skip_bridged_view_demo_SkipBridgedDemoView_Swift_1projectionImpl")
func SkipBridgedDemoView_Swift_projectionImpl(_ Java_env: JNIEnvPointer, _ Java_target: JavaObjectPointer, _ options: Int32) -> JavaObjectPointer {
    let projection = SkipBridgedDemoView.fromJavaObject(Java_target, options: JConvertibleOptions(rawValue: Int(options)))
    let factory: () -> Any = { projection }
    return SwiftClosure0.javaObject(for: factory, options: [])!
}

which results in the error:

[0/14] Write swift-version-3CAACD0405DA904A.txt
[2/9] Emitting module SkipBridgedViewDemo
[3/9] Compiling SkipBridgedViewDemo SkipBridgeViewDemo_Bridge.swift
/Users/marc/Library/Developer/Xcode/DerivedData/Skip-Everything-aqywrhrzhkbvfseiqgxuufbdwdft/Build/Intermediates.noindex/BuildToolPluginIntermediates/skipapp-howdy.output/HowdySkip/skipstone/HowdySkip/build/swift/plugins/outputs/skip-bridged-view-demo/SkipBridgedViewDemo/destination/skipstone/SkipBridgeGenerated/SkipBridgeViewDemo_Bridge.swift:31:78: error: cannot find 'View_BridgeImpl' in scope
29 |             return jniContext {
30 |                 let value_java: JavaObjectPointer = try! Java_peer.call(method: Self.Java_get_body_methodID, options: [], args: [])
31 |                 return AnyBridging.fromJavaObject(value_java, options: []) { View_BridgeImpl.fromJavaObject(value_java, options: []) as Any } as! (any View)
   |                                                                              `- error: cannot find 'View_BridgeImpl' in scope
32 |             }
33 |         }

/Users/marc/Library/Developer/Xcode/DerivedData/Skip-Everything-aqywrhrzhkbvfseiqgxuufbdwdft/Build/Intermediates.noindex/BuildToolPluginIntermediates/skipapp-howdy.output/HowdySkip/skipstone/HowdySkip/build/swift/plugins/outputs/skip-bridged-view-demo/SkipBridgedViewDemo/destination/skipstone/SkipBridgeGenerated/SkipBridgeViewDemo_Bridge.swift:29:20: error: type 'any View' cannot conform to 'View'
25 |     private static let Java_constructor_0_methodID = Java_class.getMethodID(name: "<init>", sig: "()V")!
26 | 
27 |     public var body: (some View) {
   |                      `- note: required by opaque return type of property 'body'
28 |         get {
29 |             return jniContext {
   |                    |- error: type 'any View' cannot conform to 'View'
   |                    `- note: only concrete types such as structs, enums and classes can conform to protocols
30 |                 let value_java: JavaObjectPointer = try! Java_peer.call(method: Self.Java_get_body_methodID, options: [], args: [])
31 |                 return AnyBridging.fromJavaObject(value_java, options: []) { View_BridgeImpl.fromJavaObject(value_java, options: []) as Any } as! (any View)

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions