Klassenvariablen werden noch nicht unterstützt

93

Ich beginne mein Projekt mit einem Split View Controller als Initial View Controller und starte es automatisch vom Storyboard aus.

Im Allgemeinen hat eine App mit dieser Benutzeroberfläche nur einen Split-View-Controller als Root. Daher erstelle ich eine statische Variable in der Unterklasse und lege sie fest, wenn die Initialisierung abgeschlossen ist.

Also möchte ich dieses Verhalten schnell ausprobieren.

Ich habe das Swift-Programmiersprachenhandbuch auf iBook über Typeigenschaften (mit statischem Schlüsselwort und Klassenschlüsselwort) gelesen und versucht, einen Code für den Job zu finden:

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

Aber ich habe herausgefunden, wann Xcode sagt, dass das Klassenschlüsselwort für Typeneigenschaften noch nicht unterstützt wird.

Fehlerdetail im Bild

Hattest du eine Lösung dafür?

Vincent Saluzzo
quelle
Was passiert, wenn Sie 'let' durch 'var' ersetzen?
ZunTzu
Es ergibt sich der gleiche Fehler.
Cezar
1
Es ist der erste Same, beruhige dich. :) Wenn das Buch sagt , dass es unterstützt und es ist noch nicht verfügbar, es wird sein. Sogar der Fehler sagt "noch" .
Akashivskyy
1
Ja @akashivskyy Sie haben Grund, aber es könnte sein, dass es ein Fehler auf meiner Seite ist und jemand eine Lösung hat, um dieses Verhalten zu tun ...
Vincent Saluzzo
1
@lespommes Apple ist bekanntermaßen über alles, was noch aussteht, sehr gespannt. Es ist für sie peinlich, dass ein derart standardmäßiges und offensichtliches Merkmal bei der Veröffentlichung ihrer neuen Flaggschiff-Sprache fehlte. Es sind viele Verbesserungen erforderlich, bevor Swift für den ernsthaften Einsatz bereit ist.
Hyperbole

Antworten:

37

Swift unterstützt jetzt statische Variablen in Klassen. Dies ist nicht genau das Gleiche wie eine Klassenvariable (da sie nicht von Unterklassen geerbt werden), aber es bringt Sie ziemlich nahe:

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

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

X.x = 5

println(X.x)
Rechnung
quelle
1
Wie Bill sagt, das ist nicht dasselbe, aber das brauche ich!
Vincent Saluzzo
@ VincentSaluzzo, (und Bill) Was ist der Unterschied zwischen dieser und der Klassenvariablen?
Skywinder
Die Apple-Dokumentation wurde kürzlich in den Aktualisierungsstatus geändert: developer.apple.com/library/ios/documentation/Swift/Conceptual/… Tatsächlich kann das classSchlüsselwort jetzt nur für berechnete Eigenschaften verwendet werden, und statisch gilt für alle Typeneigenschaften (in Aufzählung, Klasse) oder Struktur)
Vincent Saluzzo
@skywinder Wie ich in meiner Antwort erwähnt habe, können echte Klassenvariablen von Unterklassen geerbt werden. Statische Variablen können nicht.
Bill
@ VincentSaluzzo Aktualisiert Apple sein Dokument? developer.apple.com/library/ios/documentation/Swift/Conceptual/… Schauen Sie sich den vierten Absatz an: "Für Werttypen (dh Strukturen und Aufzählungen) können Sie gespeicherte und berechnete Typeneigenschaften definieren. Für Klassen können Sie Definieren Sie nur berechnete Typeneigenschaften. "
Fujianjin6471
73

Das Einbetten einer Struktur kann als Problemumgehung problemlos funktionieren:

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

Die berechnete Typ-Eigenschaft SomeClass.workaroundClassVariable kann dann so verwendet werden, als wäre sie eine gespeicherte Typ-Eigenschaft.

Glessard
quelle
1
Arbeitete für mich - außer dass ich die 'public' löschen musste, da XCode 6.0 nicht mochte, dass ich eine öffentliche Klasse innerhalb einer internen Klasse deklarierte.
Ali Beadle
Funktioniert hervorragend, außer dass xcode keinen verschachtelten Typ in einem generischen Typ zulässt. Wenn Sie also eine generische Klasse haben, erscheint dies eher hoffnungslos, da nur berechnete Eigenschaften möglich sind.
BenMQ
19

Es scheint möglich zu sein, Variablen mit statischer Speicherdauer im Dateibereich zu deklarieren (wie in C):

var sharedInstance: SplitViewController? = nil

class SplitViewController: UISplitViewController {
    ....
    func initialization() {
        sharedInstance = self
    }
}
Nikolai Ruhe
quelle
mmmh, warum nicht, aber eine Variable im Dateibereich definieren führt bei langer Nutzung nicht zu einem Speicherverlust?
Vincent Saluzzo
@VincentSaluzzo Es gibt keinen Unterschied zu dem, was Sie vor Swift getan haben: Speichern Sie die einzige Instanz in einer statischen Variablen. Hier gibt es nichts zu verlieren, außer der einzelnen Instanz, die so lange lebt wie der Prozess.
Nikolai Ruhe
Ich habe es auf dem Spielplatz mit meiner eigenen Klasse versucht. Es funktioniert nicht, da die Klasse noch nicht deklariert wurde, als Sie diese "statische" Variable initialisiert haben. Ich habe es im Xcode-Projekt nicht ausprobiert (ich denke, es muss dort funktioniert haben?). Daher muss ich möglicherweise die "Klassenvorwärtsdeklaration" herausfinden, wie Sie es immer tun, wenn Sie ein Protokoll für eine Klasse angeben.
Kawingkelvin
2
Beachten Sie, dass Sie in Xcode 6.0 nicht zwei Dateibereichsvariablen mit demselben Namen haben können, selbst wenn dies der Fall ist private.
Nschum
@ NikolayTsenkov Genau.
Nikolai Ruhe
14

Meine bevorzugte Methode besteht darin, nur eine private Dateibereichsvariable außerhalb der Klasse zu verwenden und dann klassen- / statische Getter und Setter zu implementieren:

private var _classVar: Int = 0;

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

Ab Swift 1.2 (verfügbar mit Xcode 6.3b1 und höher) werden staticKlasseneigenschaften und -methoden unterstützt.

class SomeClass
{
    static var someVariable: Int = 0
}
Andreas Ley
quelle
1
Haben Sie festgestellt, ob die classVariable nur veraltet ist, oder gibt es eine Unterscheidung (früher staticfür Strukturen, classfür Klassen)?
Chris Conover
@chrisco In den Versionshinweisen wird angegeben, dass dies staticein Alias ​​für ist class final.
Andreas Ley
4

Eine Lösung, die im Dateibereich ähnlich wie var ist, jedoch anpassbarer und in der Nähe von Singleton ist, besteht darin, eine Struktur zu verwenden, die statische var als Eigenschaft der Klasse unterstützt

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
quelle
2

Ok, mit der Lösung von Nikolai, die die Arbeit macht. Ich poste meine Änderungen in diesem Thread zur 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
    }
}

In meinem appDelegate kann ich beispielsweise auf diese statische Methode zugreifen

SplitViewController.sharedInstance()!.presentsWithGesture = false
Vincent Saluzzo
quelle
Ich bin nur neugierig, aber ist die Variable "Instanz" dann keine globale Variable? Dies würde bedeuten, dass wenn Sie eine andere Singleton-Klasse haben, Ihre Variable "Instanz" überschrieben wird, oder?
Raphael
1

Der Wortlaut des Fehlers impliziert stark, dass dies in Zukunft ein Sprachmerkmal sein wird.

Möglicherweise möchten Sie vorübergehend eine Eigenschaftsvariable im Anwendungsdelegierten deklarieren und von dort abrufen. Nicht ideal, definitiv ein Anti-Muster, aber es würde Ihnen einen zentralen Ort geben, an dem Sie das UISplitViewControllerbei Bedarf abrufen können.

Cezar
quelle
Nein, da in meinem Fall der SplitViewController zur Laufzeit vom Storyboard aus zur Laufzeit initialisiert wurde, sodass ich von meinem Anwendungsdelegierten
Vincent Saluzzo
1

Sie müssen die Klassenvariablen in eine innere Strukturvariable einschließen

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
quelle
0

Versuche dies:

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

In Swift heißt es Type Property .

Sie definieren Typeneigenschaften mit dem Schlüsselwort static. Für berechnete Typeneigenschaften für Klassentypen können Sie stattdessen das Schlüsselwort class verwenden, damit Unterklassen die Implementierung der Oberklasse überschreiben können. Das folgende Beispiel zeigt die Syntax für gespeicherte und berechnete Typeneigenschaften:

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

Lesen Sie mehr unter dem Link unten,

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

Lorem
quelle