niklassaers
niklassaers

Reputation: 8810

Default arguments in Swift enums

I make SnapOperationQueue which is an operation queue with a few extensions I like. One of them is reprioritisation of groups of operations. An operation is added with one of these four priorities (SnapOperationQueuePriority):

case Highest
case High
case Normal
case Low

In the current implementation I have it so that .Low and .Highest will not change, but .High and .Normal will.

I would like to change this so that I can have upper and lower thresholds on priorities. I.e, I can say that this operation that we might as well do now (.Low) can become super-important in a bit (.High) i.e. when pre-caching images and that image is all the sudden needed on screen. These thresholds should also be able to say that some operations, even in a group that is reprioritised, will not be reprioritised lower than something, i.e. a login operation (.Highest) should remain .Highest

To do this, I wanted to modify my enum like this:

case Highest(lowerThreshold: SnapOperationQueuePriority = .Highest)
case High(lowerThreshold: SnapOperationQueuePriority = .Low, higherThreshold: SnapOperationQueuePriority = .High)
case Normal(lowerThreshold: SnapOperationQueuePriority = .Low, higherThreshold: SnapOperationQueuePriority = .High)
case Low(higherThreshold: SnapOperationQueuePriority = .Low)

However, I get "Default argument not permitted in a touple type". The reason I want to have default arguments here is so that this change won't break or change behaviour of any code that is already using the existing implementation.

Can you suggest a way in which I can get my new priorities yet don't change the API for code that depends on the current API?

Upvotes: 9

Views: 4600

Answers (2)

sketchyTech
sketchyTech

Reputation: 5906

FYI: Default parameter values are now allowed after Swift 5.1. This answer only applies to versions of Swift before that.


This is a tricky one because you cannot have default values, you cannot have stored properties and you cannot repeat case names in enums. The best thing I can think to do is to create an init() and some semi-private cases.

enum SnapOperationQueuePriority {
    case Highest, High, Low, Default
}

enum SnapOperationQueue {
    case Highest, High, Normal, Low

    case _Highest(lowerThreshold: SnapOperationQueuePriority)
    case _High(lowerThreshold: SnapOperationQueuePriority, higherThreshold: SnapOperationQueuePriority)
    case _Normal(lowerThreshold: SnapOperationQueuePriority, higherThreshold: SnapOperationQueuePriority)
    case _Low(higherThreshold: SnapOperationQueuePriority)

    init(queue:SnapOperationQueue, lowerThreshold:SnapOperationQueuePriority = .Default, higherThreshold:SnapOperationQueuePriority = .Default) {
        switch queue {
        case .Highest:
            self = ._Highest(lowerThreshold: lowerThreshold == .Default ? .Highest : lowerThreshold)
        case .High:
            self = ._High(lowerThreshold: lowerThreshold == .Default ? .Low : lowerThreshold, higherThreshold: higherThreshold == .Default ? .High : higherThreshold)
        case .Normal:
            self = ._Normal(lowerThreshold: lowerThreshold == .Default ? .Low : lowerThreshold, higherThreshold: higherThreshold == .Default ? .High : higherThreshold)
        case Low:
            self = ._Low(higherThreshold: higherThreshold == .Default ? .Low : higherThreshold)
        default:
            self = queue

        }
    }
}

SnapOperationQueue.Normal
SnapOperationQueue(queue: .Normal)
SnapOperationQueue(queue: .High, lowerThreshold: .High, higherThreshold: .Highest)

This keeps old implementations valid and catches new ones made using init. In addition you might add a method like this to the enum:

func queue() -> SnapOperationQueue {
    switch self {
    case .Highest:
        return SnapOperationQueue(queue: .Highest)
    case .High:
        return SnapOperationQueue(queue: .High)
    case .Normal:
        return SnapOperationQueue(queue: .Normal)
    case Low:
        return SnapOperationQueue(queue: .Low)
    default:
        return self

    }

}

So that you can transform the old types of enum cases into the new, e.g. SnapOperationQueue.Normal.queue()

Upvotes: 6

Gobe
Gobe

Reputation: 2717

This is now possible starting with Swift 5.1 (Xcode 11)

See the feature proposal.

Upvotes: 5

Related Questions