Reputation: 8810
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
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