Swift catch enum case with binding
If I understand you correctly, you want a variable inside a catch to be the specific error case of a specific type of error.
If so, you can do this:
do {
try something()
} catch let err1 as MyError where err1 == .error1 {
print(err1)
} catch {
print(error)
}
Binding to an associated value of an enum
You can extend your enumeration and add a text property with a getter and a setter:
extension Choice {
var text: String {
get {
switch self {
case let .one(string): return string
case let .two(string): return string
}
}
set {
switch self {
case .one: self = .one(newValue)
case .two: self = .two(newValue)
}
}
}
}
Then you can simply pass the text property:
TextField("", text: $choice.text)
How can I use enum to Binding data in SwiftUI?
Using a brandProxy
to maintain the integrity of the other Car
variables
import SwiftUI
enum Brand: Int, CaseIterable, Codable {
case toyota = 0
case mazda
case suzuki
case unknown
func description() -> String {
var result = "unknown"
switch self {
case .toyota:
result = "toyota"
case .mazda:
result = "mazda"
case .suzuki:
result = "suzuki"
case .unknown:
result = "unknown"
}
return result
}
}
struct CarView: View {
//This makes it mutable
@State var car: Car
var brandProxy: Binding<Int> {
Binding<Int>(
get: {
car.brand.rawValue
},
set: {
car.brand = Brand(rawValue: $0) ?? Brand.unknown
}
)
}
var body: some View {
VStack{
Text(car.brand.description())
SomeView(selectedIndex: brandProxy)
}
}
}
How to create a Binding to an enum in Swift?
As an alternative to @Binding
you can use @Published
in @ObservableObject
:
class ViewModel: ObservableObject {
@Published var lifeEvent: LifeEvent? {
didSet { // or alternatively willSet (depending on the use case)
// do whatever you need just after the lifeEvent is changed
}
}
}
struct TimeSpanEditView: View {
@ObservedObject private var viewModel = ViewModel()
...
}
And access your binding like this:
self.$viewModel.lifeEvent
Binding to an associated value of an enum that has different types of associated values
Indeed, having several very similar properties is a code smell, as well as the fact that those properties were added just because they are needed by the UI layer.
However, since you already have the switch over the value type, you can push the logic for the binding to that (UI) layer. Here's a possible implementation:
struct ValueView: View {
let name: String
@Binding var value: Value
var body: some View {
HStack {
switch value {
case .none:
Spacer()
case let .bool(bool):
Toggle(name, isOn: Binding(get: { bool }, set: { value = .bool($0) } ))
case let .int(int):
Stepper("\(int)", value: Binding(get: { int }, set: { value = .int($0) }))
case let .float(float):
Text(float.description)
case let .string(string):
Text(string)
}
}
}
}
I also took the liberty of extracting the code to a dedicated view and decoupling that view from the Node
type, this is more idiomatic in SwiftUI and makes your code more readable and easier to maintain.
With the above in mind, ContentView
simply becomes:
Usage:
struct ContentView: View {
@StateObject private var model = Model()
var body: some View {
VStack {
ScrollView {
Text(model.jsonString)
}
List($model.data, id: \.name, children: \.children) { $node in
ValueView(name: node.name, value: $node.value)
}
}
}
}
, and you can safely delete the "duplicated" properties from the Value
enum.
Use Guard to trap all enum states other than one
It is impossible to negate a case
statement.
You either need to use your if
statement, or make the enumeration Equatable
, in which case you would just drop the case keyword.
guard foundTransition.validToObject.isInSituation != .notInUse
Alternatively, you can use a guard
statement that is backed by a switch
or if
. But you'll never get rid of them! /p>
guard ({
if case .notInUse = foundTransition.validToObject.isInSituation {
return false
}
return true
} ()) else {
fatalError("Transition: The toObject is already in a situation")
}
Swift Catch Pattern that binds the error to a variable
The syntax used in a catch
line is exactly the same pattern syntax used in the case
of a switch
. If you know how to write a case
you know how to write a catch
.
So, for example, you complain:
} catch let decodingError is DecodingError { // THIS IS NOT VALID
Right. But this is valid:
} catch let decodingError as DecodingError {
Oh what a difference one letter makes.
swift enum get the associated value of multiple case with same parameters in single switch-case
You can put multiple enum values in the same case
line, but you have to move the let
into the ()
:
var value: Double {
switch self {
case .width(let value), .height(let value), .xxxxx1(let value):
return value
}
}
You might want to put each enum
value on a separate line:
var value: Double {
switch self {
case .width(let value),
.height(let value),
.xxxxx1(let value):
return value
}
}
Unfortunately, that's about as elegant as it gets with enum
s with associated values. There's no way to get the associated value without explicitly listing the enum
s.
You can only combine values in the same line that have the same type of associated value, and all of the values have to bind to the same variable name. That way, in the code that follows, you know that the value
is bound and what its type is no matter which enum
pattern matched.
Related Topics
Swift Implement Literalconvertible Protocol
Can Openssl Be Bundled for Wget Wrapper App to Reference in Xcode Project
Downloading Firebase Storage Files Device Issue
Iterate a Grid of Views Swiftui
How to Make a Uiview Grow in Uiview.Animate() with an Accurate Corner Radius
Saving Bool/ Tableview Checkmark - 3Rd Time Lucky
Sorting Several Arrays According to One Array
Swiftui: Stop an Animation That Repeats Forever
Accessing Actor Properties Synchronously from Task-Less Context
Why Does the Compiler Not See the Default Code in a Protocol
Background Thread Core Data Object Property Changes Doesn't Reflect on Ui
Accessing and Manipulating Array Item in an Environmentobject
How to Sort an Array of Posts by Their Elements
Update All Value in One Attribute Core Data
Enum Method Returning a Dynamic Type
How to Use Dispatchgroup/Gcd to Execute Functions Sequentially in Swift