HiveBrain v1.2.0
Get Started
← Back to all entries
patternswiftMinor

Equivalent of C-style "Static Local Variable" in Swift

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
swiftlocalequivalentstylevariablestatic

Problem

I'm porting some Obj-C code to Swift, and I've written the following code to allow me to deal with "static local variables" which do not exist in Swift.

A static local variable has these requirements:

  • it is shared between all instances that access it



  • it has one assignment method which only sets the value when it is first declared.



  • has another assignment method which sets its value normally (i.e. any time it is used)



There has to be a better way then what I have coded. For starters, I know that using UnsafeBitcast is not good practice.

class Container{

    var _memory:Any
    var memory:T {
        get {

            if let typed_value = self._memory as? T {
                // for value types, such as "String"
                return typed_value
            } else {
                // for types conforming to "AnyObject", such as "NSString"
                return unsafeBitCast( self._memory, T.self )
            }

        }
        set {
            self._memory = newValue
        }
    }

    init( memory:Any ){
        self._memory = memory
    }

}

var Static_Containers = [String:AnyObject]()

func static_var (
    value:T,
    file: StaticString = __FILE__,
    line: UWord = __LINE__,
    col: UWord = __COLUMN__,
    fun: StaticString = __FUNCTION__
) -> Container {

        let unique_key = "FUNC_\(fun)__LINE\(line)_COL\(col)__FILE_\(file)"

        let needs_init = !contains( Static_Containers.keys, unique_key )

        if needs_init {
            Static_Containers[unique_key] = Container( memory:value )
        }

        return Static_Containers[unique_key]! as! Container

}


Here's a couple tests:

```
func test_with_nsstring( str:NSString, init_only:Bool ) -> NSString {
var stat_str = static_var( str )
if !init_only {
stat_str.memory = str
}
return stat_str.memory
}
test_with_nsstring( "this should get set", true )
test_with_nsstring( "this should be ignored", true ) // only repeated declaration
test_with

Solution

The only work around for this that I've come up with thus far is something that looks like this:

func foo() -> Int {
    struct Holder {
        static var timesCalled = 0
    }
    return ++Holder.timesCalled;
}


It's pretty clunky in my opinion, and I'm not sure why Apple doesn't just allow straight static function variables, but this seems quite a bit cleaner than your approach.

Code Snippets

func foo() -> Int {
    struct Holder {
        static var timesCalled = 0
    }
    return ++Holder.timesCalled;
}

Context

StackExchange Code Review Q#83418, answer score: 8

Revisions (0)

No revisions yet.