尚不支持类变量

我以一个分割视图控制器作为初始视图控制器开始我的项目,并从故事板自动启动它。

通常,具有这个 UI 的应用程序将 只有一个分割视图控制器作为 root 用户,所以我在子类中创建一个 静态变量,并在初始化完成时设置它。

所以我想用迅捷来尝试这种行为。

我在 iBook 上阅读了 Swift 编程语言指南关于 Type 属性(带有 static 和 class 关键字)的书,并尝试了一段代码来完成这项工作:

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;
}
}

但是我发现当 Xcode 说 type 属性的 class 关键字还不被支持的时候。

error detail in image

你有解决办法吗?

66167 次浏览

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.

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
}
}

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

Using a dispatch_once singleton model in Swift

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

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
}

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.

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

Try this:

class var instance: SplitViewController {
return nil
}

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 }
}
}

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
}

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)

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