Adding a case to an existing enum with a protocol
Design
The work around is to use a struct
with static
variables.
Note: This is what is done in Swift 3 for Notification.Name
Below is an implementation on Swift 3
Struct:
struct Car : RawRepresentable, Equatable, Hashable, Comparable {
typealias RawValue = String
var rawValue: String
static let Red = Car(rawValue: "Red")
static let Blue = Car(rawValue: "Blue")
//MARK: Hashable
var hashValue: Int {
return rawValue.hashValue
}
//MARK: Comparable
public static func <(lhs: Car, rhs: Car) -> Bool {
return lhs.rawValue < rhs.rawValue
}
}
Protocol
protocol CoolCar {
}
extension CoolCar {
static var Yellow : Car {
return Car(rawValue: "Yellow")
}
}
extension Car : CoolCar {
}
Invoking
let c1 = Car.Red
switch c1 {
case Car.Red:
print("Car is red")
case Car.Blue:
print("Car is blue")
case Car.Yellow:
print("Car is yellow")
default:
print("Car is some other color")
}
if c1 == Car.Red {
print("Equal")
}
if Car.Red > Car.Blue {
print("Red is greater than Blue")
}
Note:
Please note this approach is not a substitute for enum
, use this only when the values are not known at compile time.
Creating enum cases dynamically
One idea is to use a struct as an intermediary between data and the view controller. This struct can be created and used by a method like tableview's cell count; each time your view needs to know its layout, it constructs itself using whether or not there exists pending data.
enum Section: Int, CaseIterable {
case title, accounts, pending, total
}
struct SectionData {
var sections: [Section]
init(hasPendingData: Bool) {
if (hasPendingData) {
sections = Section.allCases
} else {
sections = [.title, .accounts]
}
}
}
class MyViewController: UIViewController {
var pendingModelData: Data?
func sectionCount() -> Int {
return SectionData(hasPendingData: pendingModelData != nil).sections.count
}
}
Going a step further, you could use didSet on pendingModelData to update the view displaying sections.
Swift - extend an enum for only one of its cases
Moved from comments:
I think here enum is not a best idea. You should try to do this with protocol + 3 classes/structs implementing it. That will allow you both extend "only one case" and add more "cases" in it. Like here.
Quick info about linked article:
Why I don’t love Swift Enums any more
At the last two Sydney Cocoaheads, any time I see a use of Enums in a talk, I make sure to ask “Why an enum and not a protocol?”. This blog post will hopefully explain the smell of enums.
Firstly, I have to say that enums are great if you never need to extend the number of cases. However, incorrect usages of enums break the O in SOLID Principles.
Open Close Principle
A Type should be open to extension, but closed for edits.
And I believe the Expression Problem best explains the violation.
The Expression Problem
Add new methods; add new cases. Pick one.
I will attempt to walk you through the Expression Problem with enums, then proceed to “solve” it with the Visitor Pattern.
Swift enum inheritance
In Swift language, we have Structs, Enum and Classes. Struct and Enum are passed by copy but Classes are passed by reference. Only Classes support inheritance, Enum and Struct don't.
So to answer your question, you can't have inheritance with Enum (and Struct types). Have a look here:
stackOverflow difference classes vs structs
How to design for a future additional enum value in protocol buffers?
Yes, the best approach is to make the first value in the enum something like UNKNOWN = 0
. Then old programs reading a protobuf with an enum value they don't recognize will see it as UNKNOWN
and hopefully they can handle that reasonably, eg by skipping that element.
If you want to do this you'll also want to make the enum be optional
not required
.
required
, generally, means "I'd rather the program just abort than handle something it doesn't understand."
Note that it must be the first value declared in the proto source - just being the zero value doesn't make it the default.
Swift Enum associated values conforming to single protocol
I've found the solution in case anyone will need this too.
enum ContentType {
case content1(Type1 & Refreshable)
case content2(Type2 & Refreshable)
case content3(someLabel: Type3 & Refreshable)
func refreshMe() {
let caseReflection = Mirror(reflecting: self).children.first!.value
(caseReflection as? Refreshable)?.refresh() //If associated type doesn't have label
let refreshable = Mirror(reflecting: caseReflection).children.first?.value as? Refreshable
refreshable?.refresh() //If associated type has label
}
}
How to make an enum conform to Hashable with the API available in Xcode 10?
You can use autogenerated Hashable
conformance, as proposed in the other answer (under condition your type doesn't contains any date of non-Hashable
types).
But that's what you can do in the general case(autogenerated code would probably look like that too):
extension MyEnum: Hashable {
func hash(into hasher: inout Hasher) {
switch self {
case .caseOne(let value):
hasher.combine(value) // combine with associated value, if it's not `Hashable` map it to some `Hashable` type and then combine result
case .caseTwo(let value):
hasher.combine(value) // combine with associated value, if it's not `Hashable` map it to some `Hashable` type and then combine result
case .caseThree:
// you can `combine` with some `Hashable` constant, but here it's ok just to skip
break
}
}
}
Related Topics
How to Add Kerning to a Textfield in Swiftui
Call Completion Block When Two Other Completion Blocks Have Been Called
Swiftui - Wait Until Firestore Getdocuments() Is Finished Before Moving On
Self' Captured by a Closure Before All Members Were Initialized
Why How to Use Codable with a Project Language Version of Swift 3.3
How to Limit Flatmap Concurrency in Combine Still Having All Source Events Processed
Swift Http Request Use Urlsession
Compare Textfield.Text to Firebase String Swift
How to Test If Objects Conforming to the Same Protocol Are Identical in Swift Without Casting
Parse.Com Querying User Class (Swift)
Why I Can Change/Reassigned a Constant Value That Instantiated from a Class
Format Realtime Stopwatch Timer to the Hundredth Using Swift
Function Throws and Returns Optional.. Possible to Conditionally Unwrap in One Line
Converting a C-Style for Loop That Uses Division for the Step to Swift 3
Know When an Iteration Over Array with Async Method Is Finished
Bool Being Seen as Int When Using Anyobject
Checking If an Array of Custom Objects Contain a Specific Custom Object