Binding issues when transpiling
Nobody has claimed this yet.
- Dominant language
- Swift
- Stars
- 330
- Forks
- 76
- Avg merge
- 3h 6m
- Merged PRs (30d)
- 1
Description
Hello! I'm trying to work with bindings to optional environment objects and bindings to optional fields within those objects. I could get what I want to work with pure Swift, but transpiling fails when trying to get a non optional binding from an optional one.
I'm a SwiftUI newbie myself, so please advise if there's a better or feasible way to approach the problem.
I built this sample to showcase what I'm going through:
import SwiftUI
struct MyModel: Hashable, Codable {
var optionalVar: String?
var nonOptionalVar: String
}
final class ModelManager: ObservableObject {
@Published var optionalModel: MyModel?
@Published var nonOptionalModel: MyModel
init(optionalModel: MyModel? = nil, nonOptionalModel: MyModel) {
self.optionalModel = optionalModel
self.nonOptionalModel = nonOptionalModel
}
}
struct ContentView: View {
@EnvironmentObject var modelManager: ModelManager
var body: some View {
VStack {
TextField("Swift ✅ | Skip ✅", text: $modelManager.nonOptionalModel.nonOptionalVar)
TextField("Swift ✅ | Skip ✅", text: Binding.unwrap($modelManager.nonOptionalModel.optionalVar, default: ""))
// Get a nonOptional binding from the optional binding
if let nonOptionalBinding = Binding($modelManager.optionalModel) {
TextField("Swift ✅ | Skip ❌", text: nonOptionalBinding.nonOptionalVar)
TextField("Swift ✅ | Skip ❌", text: Binding.unwrap(nonOptionalBinding.optionalVar, default: ""))
} else {
Text("Model is nil!")
}
}
}
}
public extension Binding {
/// Create a non-optional version of an optional `Binding` with a default value
/// - Parameters:
/// - lhs: The original `Binding<Value?>` (binding to an optional value)
/// - rhs: The default value if the original `wrappedValue` is `nil`
/// - Returns: The `Binding<Value>` (where `Value` is non-optional)
static func unwrap(_ binding: Binding<Value?>, `default`: Value) -> Binding<Value> {
Binding {
binding.wrappedValue ?? `default`
} set: {
binding.wrappedValue = $0
}
}
}
The failing transpiled code is like this:
// Get a nonOptional binding from the optional binding
val matchtarget_0 = Binding(Binding({ _modelManager.wrappedValue.optionalModel }, { it -> _modelManager.wrappedValue.optionalModel = it }))
if (matchtarget_0 != null) {
val nonOptionalBinding = matchtarget_0
TextField(LocalizedStringKey(stringLiteral = "Swift ✅ | Skip ❌"), text = nonOptionalBinding.nonOptionalVar).Compose(composectx)
TextField(LocalizedStringKey(stringLiteral = "Swift ✅ | Skip ❌"), text = Binding.unwrap(nonOptionalBinding.optionalVar, default = "")).Compose(composectx)
} else {
Text(LocalizedStringKey(stringLiteral = "Model is nil!")).Compose(composectx)
}
nonOptionalBinding members are reported as unresolved references.
Any help is appreciated!
Thanks for the awesome work on this project!
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the SwiftUI sample in the issue and compare its optional Binding conditional with the shown transpiled Kotlin code. Trace how the optional binding and its member accesses are emitted, then verify that nonOptionalBinding members resolve and the sample transpiles successfully.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kotlin, swift
- Domain
- compilers, mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100