Variables de clase aún no admitidas

93

Comienzo mi proyecto con un controlador de vista dividida como controlador de vista inicial y lo inicio automáticamente desde el guión gráfico.

Generalmente, una aplicación con esta interfaz de usuario tiene uno y solo un controlador de vista dividida como raíz, por lo que creo una variable estática en la subclase y la configuro cuando se realizó la inicialización.

Así que quiero probar este comportamiento con rapidez.

Leí la guía del lenguaje de programación Swift en el iBook sobre las propiedades de tipo (con palabras clave estáticas y de clase) y probé un fragmento de código para el trabajo:

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

pero descubrí cuando Xcode dice que la palabra clave de clase para las propiedades de tipo aún no es compatible.

detalle del error en la imagen

¿Tenías una solución para hacer esto?

Vincent Saluzzo
fuente
¿Qué sucede si reemplaza 'let' con 'var'?
ZunTzu
Produce el mismo error.
Cezar
1
Es la primera semilla, cálmate. :) Si el libro dice que es compatible y aún no está disponible, lo estará . Incluso el error dice "todavía" .
akashivskyy
1
Sí @akashivskyy, tienes una razón, pero puede ser que sea un error de mi lado y alguien tenga una solución para hacer este comportamiento ...
Vincent Saluzzo
1
@lespommes Apple es notoriamente reservado sobre todo lo que está pendiente. Es vergonzoso para ellos que faltara una característica tan estándar y obvia en el gran lanzamiento de su nuevo lenguaje insignia. Se requieren muchas mejoras antes de que Swift esté listo para un uso serio.
Hipérbole

Respuestas:

37

Swift ahora tiene soporte para variables estáticas en clases. Esto no es exactamente lo mismo que una variable de clase (porque no las heredan las subclases), pero te acerca bastante:

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

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

X.x = 5

println(X.x)
Cuenta
fuente
1
Como dice Bill, eso no es lo mismo, ¡pero eso es lo que necesito!
Vincent Saluzzo
@VincentSaluzzo, (y Bill) ¿Cuál es la diferencia entre esta variable y la de clase?
skywinder
La documentación de Apple ha cambiado recientemente para actualizar el estado: developer.apple.com/library/ios/documentation/Swift/Conceptual/… De hecho, la classpalabra clave solo se puede usar para propiedades calculadas ahora y estática para todas las propiedades de tipo (en enum, class or struct)
Vincent Saluzzo
@skywinder Como mencioné en mi respuesta, las subclases pueden heredar las verdaderas variables de clase. Las variables estáticas no pueden.
Proyecto de ley
@VincentSaluzzo ¿Apple actualiza su documento? developer.apple.com/library/ios/documentation/Swift/Conceptual/… mire el cuarto párrafo: "Para tipos de valor (es decir, estructuras y enumeraciones), puede definir propiedades de tipo almacenadas y calculadas. Para clases, puede definir solo propiedades de tipo calculado. "
fujianjin6471
73

Incrustar una estructura puede funcionar bien como solución alternativa:

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

La propiedad de tipo calculado SomeClass.workaroundClassVariable se puede utilizar como si fuera una propiedad de tipo almacenada.

glessard
fuente
1
Funcionó para mí, excepto porque tuve que eliminar el 'público' ya que a XCode 6.0 no le gustaba que declarara una clase pública dentro de una clase interna.
Ali Beadle
Funciona muy bien, excepto que xcode no permite tipos anidados en un tipo genérico ... por lo que si tiene una clase genérica, parece bastante inútil ya que solo son posibles las propiedades calculadas.
BenMQ
19

Parece ser posible declarar variables con duración de almacenamiento estático en el alcance del archivo (como en C):

var sharedInstance: SplitViewController? = nil

class SplitViewController: UISplitViewController {
    ....
    func initialization() {
        sharedInstance = self
    }
}
Nikolai Ruhe
fuente
mmmh, ¿por qué no, pero definir una var en el ámbito del archivo no produce una pérdida de memoria en un uso prolongado?
Vincent Saluzzo
@VincentSaluzzo No hay diferencia con lo que hiciste antes de Swift: almacenar la única instancia en una variable estática. No hay nada que filtrar aquí, excepto la instancia única que dura tanto como el proceso.
Nikolai Ruhe
Probé esto en el patio de recreo con mi propia clase. No funciona porque la clase aún no se ha declarado cuando inicializó esa var "estática". No lo he probado en el proyecto Xcode (¿supongo que debe haber funcionado allí?). Por lo tanto, es posible que necesite averiguar la "declaración de avance de clase" como siempre se hace cuando se especifica el protocolo para una clase.
kawingkelvin
2
Tenga en cuenta que en Xcode 6.0, no puede tener dos variables de alcance de archivo con el mismo nombre, incluso si lo están private.
nschum
@NikolayTsenkov Exactamente.
Nikolai Ruhe
14

Mi método preferido es simplemente usar un ámbito de archivo privado var fuera de la clase y luego implementar captadores y definidores de clase / estáticos:

private var _classVar: Int = 0;

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

A partir de Swift 1.2 (disponible con Xcode 6.3b1 y posteriores), staticse admiten las propiedades y métodos de clase.

class SomeClass
{
    static var someVariable: Int = 0
}
Andreas Ley
fuente
1
¿Entendiste si simplemente desaprobaron la classvariable, o hay una distinción (solía ser staticpara estructuras, classpara clases)?
Chris Conover
@chrisco Las notas de la versión indican que statices un alias de class final.
Andreas Ley
4

Una solución lo suficientemente similar a var en el alcance del archivo pero más personalizable y cercana al singleton es usar una estructura que admita var estática como propiedad de la clase

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
}
Luc-Olivier
fuente
2

Ok, con la solución de Nikolai que hace el trabajo. Publico mis cambios en este hilo para obtener información.

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

y por ejemplo, en mi appDelegate, puedo acceder a este método estático como este

SplitViewController.sharedInstance()!.presentsWithGesture = false
Vincent Saluzzo
fuente
Solo tengo curiosidad, pero ¿no es entonces la variable "instancia" una variable global? Esto significaría que si tiene otra clase singleton, su variable "instancia" se sobrescribirá, ¿verdad?
Raphael
1

La redacción del error implica en gran medida que será una característica del idioma en el futuro.

Es posible que desee recurrir temporalmente a declarar una variable de propiedad en el Delegado de aplicación y recuperarla desde allí. No es ideal, definitivamente un anti-patrón, pero le daría un lugar central para recuperarlo UISplitViewControllercuando sea necesario.

Cezar
fuente
No, porque en mi caso, el SplitViewController se inició en tiempo de ejecución cuando estaba despierto del guión gráfico, por lo que no puedo acceder directamente a este controlador de vista desde mi delegado de aplicación
Vincent Saluzzo
1

Tienes que envolver las variables de clase dentro de una variable de estructura interna

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
Morteza Shahriari Nia
fuente
0

Prueba esto:

class var instance: SplitViewController {
    return nil
}
fxchou123
fuente
0

Se llama Propiedad de tipo en Swift.

Las propiedades de tipo se definen con la palabra clave estática. Para propiedades de tipo calculado para tipos de clase, puede usar la palabra clave class en su lugar para permitir que las subclases anulen la implementación de la superclase. El siguiente ejemplo muestra la sintaxis de las propiedades de tipo almacenadas y calculadas:

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

Lea más en el enlace a continuación,

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

Lorem
fuente