Omegaman Omegaman - 6 months ago 25
Swift Question

Swift computed property templates?

Is there a way to template computed properties to avoid repeating the same code over and over? For example, right now I have a class with a block of code that looks like this:

private var _state:State?
private var _maxs:State?
private var _state1s:State?
private var _state10s:State?

var state:State? {
get {
dispatch_semaphore_wait(statephore, DISPATCH_TIME_FOREVER)
let s=_state
dispatch_semaphore_signal(statephore)
return s
}
set {
dispatch_semaphore_wait(statephore, DISPATCH_TIME_FOREVER)
_state=newValue
dispatch_semaphore_signal(statephore)
if newValue != nil {statsTest(newValue!)}
}
}

var maxs:State? {
get {
dispatch_semaphore_wait(maxphore, DISPATCH_TIME_FOREVER)
let m=_maxs
dispatch_semaphore_signal(maxphore)
return m
}
set {
dispatch_semaphore_wait(maxphore, DISPATCH_TIME_FOREVER)
_maxs=newValue
dispatch_semaphore_signal(maxphore)
}
}


var state1s:State? {
get {
dispatch_semaphore_wait(state1sphore, DISPATCH_TIME_FOREVER)
let s=_state1s
dispatch_semaphore_signal(state1sphore)
return s
}
set {
dispatch_semaphore_wait(state1sphore, DISPATCH_TIME_FOREVER)
_state1s=newValue
dispatch_semaphore_signal(state1sphore)
}
}

var state10s:State? {
get {
dispatch_semaphore_wait(state10sphore, DISPATCH_TIME_FOREVER)
let s=_state10s
dispatch_semaphore_signal(state10sphore)
return s
}
set {
dispatch_semaphore_wait(state10sphore, DISPATCH_TIME_FOREVER)
_state10s=newValue
dispatch_semaphore_signal(state10sphore)
}
}


There's an obvious pattern here, and all the repeated code just obfuscates what's happening and has led to errors as I cut/paste/edit/fail. Is there a way I can capture this pattern, and then define my properties with something like:

var state=ProtectedValue(_state,statephore)


?

Answer

This looks like a job for generics and inout variables.

func setProtectedValue<T>(inout destination: T, newValue: T, semaphore: SemaphoreType) {
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
        destination = newValue
        dispatch_semaphore_signal(semaphore)
}

at the call site:

var state10s:State? {
    get {
        //...
    }
    set {
        setProtectedValue(&_state10s, newValue, state10sphore)
    }
}