Variabili di classe non ancora supportate


93

Inizio il mio progetto con un controller di visualizzazione divisa come controller di visualizzazione iniziale e lo avvio automaticamente dallo storyboard.

In genere, un'app con questa interfaccia utente ha uno e un solo controller di visualizzazione divisa come root, quindi creo una variabile statica nella sottoclasse e la imposto al termine dell'inizializzazione.

Quindi voglio provare questo comportamento con swift.

Ho letto la guida del linguaggio di programmazione Swift su iBook sulle proprietà del tipo (con parola chiave statica e di classe) e ho provato un pezzo di codice per il lavoro:

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

ma ho capito quando Xcode dice che la parola chiave class per le proprietà del tipo non era ancora supportata.

dettaglio dell'errore nell'immagine

Avevi una soluzione per farlo?


Cosa succede se sostituisci "let" con "var"?
ZunTzu

Restituisce lo stesso errore.
Cezar

1
È il primo seme, calmati. :) Se il libro dice che è supportato e non è ancora disponibile, lo sarà . Anche l'errore dice "ancora" .
akashivskyy

1
Sì @akashivskyy hai ragione ma potrebbe essere che potrebbe essere un errore dalla mia parte e qualcuno ha una soluzione per fare questo comportamento ...
Vincent Saluzzo

1
@lespommes Apple è notoriamente a denti stretti su tutto ciò che è in sospeso. È imbarazzante per loro che una caratteristica così standard e ovvia fosse mancante dal loro enorme rilascio del loro nuovo linguaggio di punta. Sono necessari molti miglioramenti prima che Swift sia pronto per un uso serio.
Iperbole

Risposte:


37

Swift ora supporta le variabili statiche nelle classi. Questa non è esattamente la stessa di una variabile di classe (perché non sono ereditate dalle sottoclassi), ma ti avvicina molto:

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

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

X.x = 5

println(X.x)

1
Come dice Bill, non è la stessa cosa ma ne ho bisogno!
Vincent Saluzzo

@VincentSaluzzo, (e Bill) Qual è la differenza tra questa e la variabile di classe?
skywinder

La documentazione Apple è cambiata di recente per aggiornare lo stato: developer.apple.com/library/ios/documentation/Swift/Conceptual/… In effetti, la classparola chiave può essere utilizzata solo per le proprietà calcolate ora e static sono per tutte le proprietà del tipo (in enum, class o struct)
Vincent Saluzzo

@skywinder Come ho detto nella mia risposta, le vere variabili di classe possono essere ereditate dalle sottoclassi. Le variabili statiche non possono.
Bill

@VincentSaluzzo Apple aggiorna il suo documento? developer.apple.com/library/ios/documentation/Swift/Conceptual/… guarda il quarto paragrafo: "Per i tipi di valore (cioè strutture ed enumerazioni), puoi definire proprietà di tipo memorizzate e calcolate. Per le classi, puoi definire solo proprietà di tipo calcolate. "
fujianjin6471

73

Incorporare una struttura può funzionare bene come soluzione 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 proprietà di tipo calcolato SomeClass.workaroundClassVariable può quindi essere utilizzata come se fosse una proprietà di tipo archiviato.


1
Ha funzionato per me, tranne perché ho dovuto eliminare il "pubblico" poiché XCode 6.0 non mi piaceva che dichiarassi una classe pubblica all'interno di una classe interna.
Ali Beadle

Funziona alla grande, tranne per il fatto che xcode non consente il tipo annidato in un tipo generico ... quindi se hai una classe generica, sembra piuttosto senza speranza poiché sono possibili solo le proprietà calcolate.
BenMQ

19

Sembra essere possibile dichiarare variabili con durata di archiviazione statica nell'ambito del file (come in C):

var sharedInstance: SplitViewController? = nil

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

mmmh, perché no, ma definire una variabile nell'ambito del file non fa una perdita di memoria in un uso prolungato?
Vincent Saluzzo

@VincentSaluzzo Non c'è differenza rispetto a ciò che hai fatto prima di Swift: memorizza l'unica istanza in una variabile statica. Non c'è nulla da trapelare qui, tranne la singola istanza che vive finché il processo.
Nikolai Ruhe

L'ho provato nel parco giochi con la mia classe. Non funziona perché la classe non è stata ancora dichiarata quando hai inizializzato quella var "statica". Non l'ho provato nel progetto Xcode (immagino che abbia funzionato lì?). Quindi potrei aver bisogno di capire la "dichiarazione di classe in avanti" come fai sempre quando specifichi il protocollo per una classe.
kawingkelvin

2
Notare che in Xcode 6.0 non è possibile avere due variabili di ambito di file con lo stesso nome, anche se lo sono private.
nschum

@NikolayTsenkov Esattamente.
Nikolai Ruhe

14

Il mio metodo preferito è usare solo un ambito di file privato var al di fuori della classe e quindi implementare getter e setter di classe / statici:

private var _classVar: Int = 0;

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

5

A partire da Swift 1.2 (disponibile con Xcode 6.3b1 e successivi), staticle proprietà ei metodi di classe sono supportati.

class SomeClass
{
    static var someVariable: Int = 0
}

1
Hai capito se hanno appena deprecato la classvariabile, o c'è una distinzione (usato per essere staticper le strutture, classper le classi)?
Chris Conover

@chrisco Le note sulla versione indicano che staticè un alias per class final.
Andreas Ley


4

Una soluzione abbastanza simile a var nell'ambito del file ma più personalizzabile e vicino al singleton consiste nell'usare una struttura che supporti la var statica come proprietà della classe

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
}

2

Ok, con la soluzione di Nikolai che fa il lavoro. Inserisco le mie modifiche in questo thread per informazioni

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

e ad esempio, nel mio appDelegate, posso accedere a questo metodo statico come questo

SplitViewController.sharedInstance()!.presentsWithGesture = false

Sono solo curioso, ma allora la variabile "istanza" non è una variabile globale? Ciò significherebbe che se hai un'altra classe singleton la tua variabile "istanza" verrebbe sovrascritta, giusto?
Raphael

1

La formulazione dell'errore implica fortemente che questa sarà una caratteristica della lingua in futuro.

Potresti voler ricorrere temporaneamente alla dichiarazione di una variabile di proprietà in Application Delegate e recuperarla da lì. Non è l'ideale, sicuramente un anti-pattern, ma ti darebbe un posto centrale per recuperare il UISplitViewControllerquando necessario.


No perché nel mio caso, lo SplitViewController è stato inizializzato dal runtime quando è sveglio dallo storyboard, quindi non posso accedere direttamente a questo controller di visualizzazione dal mio delegato dell'applicazione
Vincent Saluzzo

1

Devi avvolgere le variabili di classe all'interno di una variabile struct 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

0

Prova questo:

class var instance: SplitViewController {
    return nil
}

0

Si chiama Type Property in Swift.

Si definiscono le proprietà del tipo con la parola chiave statica. Per le proprietà di tipo calcolate per i tipi di classe, è possibile utilizzare invece la parola chiave class per consentire alle sottoclassi di sovrascrivere l'implementazione della superclasse. L'esempio seguente mostra la sintassi per le proprietà del tipo archiviate e calcolate:

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

Leggi di più al link sottostante,

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.