Class variables not yet supported

XcodeSwift

Xcode Problem Overview


I begin my project with a split view controller as initial view controller and start it automatically from storyboard.

Generally, an app with this UI have one and only one split view controller as root, so I create a static variable in the subclass and set it when initialisation was done.

So I want try this behaviour with swift.

I read the Swift programming language guide book on iBook about Type properties (with static and class keyword) and trying a piece of code to the job:

import UIKit

class SplitViewController: UISplitViewController {
    
    class func sharedInstance() -> SplitViewController {
        return SplitViewController.instance
    }
    
    class let instance: SplitViewController = nil
    
    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        self.initialization()
    }

    init(coder aDecoder: NSCoder!) {
        super.init(coder: aDecoder);
        self.initialization()
    }
    
    func initialization() {
        SplitViewController.instance = self;
    }
}

but I figured out when Xcode say the class keyword for type properties wasn't supported yet.

error detail in image

Did you have a solution to do this ?

Xcode Solutions


Solution 1 - Xcode

Embedding a struct can work just fine as a workaround:

class SomeClass
{
  // class var classVariable: Int = 0
  // "Class variables not yet supported." Weird.
  
  // Workaround:
  private struct SubStruct { static var staticVariable: Int = 0 }

  class var workaroundClassVariable: Int
  {
    get { return SubStruct.staticVariable }
    set { SubStruct.staticVariable = newValue }
  }
}

The SomeClass.workaroundClassVariable computed type property can then be used as if it were a stored type property.

Solution 2 - Xcode

Swift now has support for static variables in classes. This is not exactly the same as a class variable (because they aren't inherited by subclasses), but it gets you pretty close:

class X {
  static let y: Int = 4
  static var x: Int = 4
}

println(X.x)
println(X.y)

X.x = 5

println(X.x)

Solution 3 - Xcode

It seems to be possible to declare variables with static storage duration in file scope (as in C):

var sharedInstance: SplitViewController? = nil

class SplitViewController: UISplitViewController {
    ....
    func initialization() {
        sharedInstance = self
    }
}

Solution 4 - Xcode

My preferred method is to just use a private file scope var outside of the class and then implement class/static getters and setters:

private var _classVar: Int = 0;

class SomeClass
{
    public class var classVar: Int
    {
        get { return _classVar }
        set { _classVar = newValue }
    }
}

Solution 5 - Xcode

As of Swift 1.2 (available with Xcode 6.3b1 and onwards), static class properties and methods are supported.

class SomeClass
{
    static var someVariable: Int = 0
}

Solution 6 - Xcode

https://stackoverflow.com/questions/24024549/dispatch-once-singleton-model-in-swift

Seems to be the best answer so far, avoiding the use of a global variable.

Solution 7 - Xcode

A solution enough similar than var in file scope but more customisable and near singleton is to use a struct which support static var as property of class

struct PersonSharedData {
    static var backstore = ""
    var data: String {
    get { return PersonSharedData.backstore }
    set { PersonSharedData.backstore = newValue }
    }
}

class Person {
    var shared=PersonSharedData() //<< pseudo class var
    var family: String {
        get { return shared.data }
        set { shared.data=newValue }
    }
    var firstname = ""
    var lastname = ""
    var sexe: Sexe = .Unknown
}

Solution 8 - Xcode

Ok, with the solution of Nikolai that do the work. I post my changes in this thread for information

var instance: SplitViewController? = nil

class SplitViewController: UISplitViewController {
    
    class func sharedInstance() -> SplitViewController? {
        return instance;
    }
    
    init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        self.initialization()
    }

    init(coder aDecoder: NSCoder!) {
        super.init(coder: aDecoder);
        self.initialization()
    }
    
    func initialization() {
        instance = self
    }
}

and for example, in my appDelegate, I can access this static method like this

SplitViewController.sharedInstance()!.presentsWithGesture = false

Solution 9 - Xcode

The wording in the error heavily implies this will be a language feature in the future.

You may want to resort temporarily to declaring a property variable in the Application Delegate and retrieve it from there. Not ideal, definitely an anti-pattern, but would give you a central place to retrieve the UISplitViewController when needed.

Solution 10 - Xcode

You have to wrap the class variables inside an inner struct variable

class Store{
    var name:String
    var address:String
    var lat:Int
    var long:Int
    init(name:String, address:String, lat:Int, long:Int){
        self.name = name
        self.address = address
        self.lat = lat
        self.long=long
    }
    
    private struct FACTORY_INITIALIZED_FLAG { static var initialized: Bool = false
       static var  myStoreList:[Store]?
        static func getMyStoreList()->[Store]{
            if !initialized{
                println("INITIALIZING")
                myStoreList = [
                    Store(name: "Walmart", address: "abcd", lat: 10, long: 20),
                    Store(name: "JCPenny", address: "kjfnv", lat: 23, long: 34)
                ]
                initialized = true
            }
                return myStoreList!
    }
    }
}


var a = Store.FACTORY_INITIALIZED_FLAG.getMyStoreList()

var b = Store.FACTORY_INITIALIZED_FLAG.getMyStoreList()

// only prints INITIALIZING once

Solution 11 - Xcode

Try this:

class var instance: SplitViewController {
    return nil
}

Solution 12 - Xcode

It is called Type Property in Swift.

> You define type properties with the static keyword. For computed type properties for class types, you can use the class keyword instead to allow subclasses to override the superclass’s implementation. The example below shows the syntax for stored and computed type properties:

struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 1
    }
}
enum SomeEnumeration {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 6
    }
}
class SomeClass {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}

Read more at link below,

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-ID254

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVincent SaluzzoView Question on Stackoverflow
Solution 1 - XcodeglessardView Answer on Stackoverflow
Solution 2 - XcodeBillView Answer on Stackoverflow
Solution 3 - XcodeNikolai RuheView Answer on Stackoverflow
Solution 4 - XcodeBobDickinsonView Answer on Stackoverflow
Solution 5 - XcodeAndreas LeyView Answer on Stackoverflow
Solution 6 - XcodeGavinView Answer on Stackoverflow
Solution 7 - XcodeLuc-OlivierView Answer on Stackoverflow
Solution 8 - XcodeVincent SaluzzoView Answer on Stackoverflow
Solution 9 - XcodeCezarView Answer on Stackoverflow
Solution 10 - XcodeMorteza Shahriari NiaView Answer on Stackoverflow
Solution 11 - Xcodefxchou123View Answer on Stackoverflow
Solution 12 - XcodeX.CreatesView Answer on Stackoverflow