How to Cast an @Binding in Swift

How can I cast an @Binding in Swift

I don’t think there’s a way to cast but you can create another Binding based on the first one:

import SwiftUI
var d = 1.0
// Create a Binding<Double> (for lack of another source)
var bd = Binding<Double>(get: { d }, set: { d = $0 })
// "Convert" to Binding<Int> by recreating another Binding
let bi = Binding<Int>(get: { Int(bd.wrappedValue) },
set: { bd.wrappedValue = Double($0) })

Using @Binding with type casting in swiftui

The Binding type allow for both reading and writing. Since you can't safely read the value of an AabbData and assume it's an AbData this cannot work.

If you want to try anyway, then you'll have to create a new Binding (possibly with the Binding(get:set:) constructor) that does the casting there.

For example, noting that this forced cast is probably not advisable for all the usual reasons:

let binding = Binding<AbData>(get: {
data.aabbData[index] as! AbData
}, set: {
data.aabbData[index] = $0
})

Casting a bindingDouble to type Int - Swift UI

@ObservedObject is a property wrapper around the actual object. So, to access the non-binding values of those properties, you could use wrappedValue:

func randomise(startNumber: Int, endNumber: Int) -> Int{


let startNum = $value.startNumber
let endNum = $value.endNumber
let generated = arc4random_uniform(UInt32(endNum.wrappedValue - startNum.wrappedValue)) + UInt32(startNum.wrappedValue)

return Int(generated)
}

OR

You could get rid of the $ when you access your value variable, removing the Binding that way:

func randomise(startNumber: Int, endNumber: Int) -> Int{


let startNum = value.startNumber
let endNum = value.endNumber
let generated = arc4random_uniform(UInt32(endNum - startNum)) + UInt32(startNum)

return Int(generated)
}

Converting optional Binding to non-optional Binding

Binding has an associated type Value already, so by trying to use T, you're putting a new generic on top of Value, which already exists.

But, you will still end up using T because you'll want to constrain Value to scenarios where it is Optional:

extension Binding {
func safeBinding<T>(defaultValue: T) -> Binding<T> where Value == Optional<T> {
.init {
self.wrappedValue ?? defaultValue
} set: { newValue in
self.wrappedValue = newValue
}
}
}

As noted in the comments, the Xcode compiler has difficulty if just Binding.init is used (note that I used just .init). This can be solved by explicitly using Binding<T>.init:

extension Binding {
func safeBinding<T>(defaultValue: T) -> Binding<T> where Value == Optional<T> {
Binding<T>.init {
self.wrappedValue ?? defaultValue
} set: { newValue in
self.wrappedValue = newValue
}
}
}

Cannot convert value of type 'BindingString?' to expected argument type 'BindingString'

Because all core data fields are optional, you have to wrap it into Binding. And as you're using core data and may face a lot of optionals, you can create an extension:

extension Binding {
func toUnwrapped<T>(defaultValue: T) -> Binding<T> where Value == Optional<T> {
Binding<T>(get: { self.wrappedValue ?? defaultValue }, set: { self.wrappedValue = $0 })
}
}

Use it like this:

TextField("title", text: $text.name.toUnwrapped(defaultValue: ""))


Related Topics



Leave a reply



Submit