Sınıf değişkenleri henüz desteklenmiyor


93

Projeme ilk görünüm denetleyicisi olarak bölünmüş görünüm denetleyicisi ile başlıyorum ve otomatik olarak film şeridinden başlatıyorum.

Genel olarak, bu kullanıcı arayüzüne sahip bir uygulama, kök olarak bir ve yalnızca bir bölünmüş görünüm denetleyicisine sahiptir, bu nedenle alt sınıfta statik bir değişken oluşturuyorum ve başlatma yapıldığında ayarlıyorum.

Bu yüzden bu davranışı hızlı bir şekilde denemek istiyorum.

İBook'ta Tür özellikleri hakkında (statik ve sınıf anahtar kelimeli) Swift programlama dili kılavuz kitabını okudum ve iş için bir kod parçası denedim:

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

ancak Xcode'un tür özellikleri için class anahtar kelimesinin henüz desteklenmediğini söylediğini anladım.

görüntüdeki hata ayrıntısı

Bunu yapmak için bir çözümünüz var mı?


'Let'i' var 'ile değiştirirseniz ne olur?
ZunTzu

Aynı hatayı verir.
Cezar

1
Bu ilk tohum, sakin ol. Kitap, desteklenen ve henüz mevcut değil diyorsa :), bu olacak olması. Hata bile "henüz" diyor .
akashivskyy

1
Evet @akashivskyy sen ... sebep yok ama olabilir olabilir ve benim yan ve birisi hata bu davranışı yapmak için bir çözüm var
Vincent Saluzzo

1
@lespommes Apple, beklemede olan her şey hakkında herkesin bildiği gibi ağzı sıkıdır. Yeni amiral gemisi dillerinin büyük sürümlerinde böylesine standart ve bariz bir özelliğin eksik olması onlar için utanç verici. Swift ciddi kullanıma hazır hale gelmeden önce yapılması gereken birçok iyileştirme var.
Abartma

Yanıtlar:


37

Swift artık sınıflardaki statik değişkenleri destekliyor. Bu, bir sınıf değişkeni ile tam olarak aynı değildir (çünkü alt sınıflar tarafından miras alınmazlar), ancak sizi oldukça yaklaştırır:

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
Bill'in dediği gibi, bu aynı değil ama ihtiyacım olan bu!
Vincent Saluzzo

@VincentSaluzzo, (ve Bill) Bu ve sınıf değişkeni arasındaki fark nedir?
skywinder

Apple belgeleri son zamanlarda durumu güncellemek için değişti: developer.apple.com/library/ios/documentation/Swift/Conceptual/… Aslında, classanahtar kelime şu anda yalnızca hesaplanan özellikler için kullanılabilir ve statik tüm tür özellikleri için (enum, or struct)
Vincent Saluzzo

@skywinder Cevabımda bahsettiğim gibi, gerçek sınıf değişkenleri alt sınıflar tarafından miras alınabilir. Statik değişkenler olamaz.
Bill

@VincentSaluzzo Apple belgesini güncelliyor mu? developer.apple.com/library/ios/documentation/Swift/Conceptual/… dördüncü paragrafa bakın: "Değer türleri için (yani yapılar ve numaralandırmalar), depolanan ve hesaplanan tür özelliklerini tanımlayabilirsiniz. Sınıflar için şunları yapabilirsiniz: yalnızca hesaplanmış tür özelliklerini tanımlayın. "
fujianjin6471

73

Bir yapıyı gömmek, geçici bir çözüm olarak gayet iyi çalışabilir:

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

SomeClass.workaroundClassVariable hesaplanan tür özelliği, daha sonra depolanmış bir tür özelliğiymiş gibi kullanılabilir.


1
Benim için çalıştı - XCode 6.0, dahili bir sınıf içinde genel bir sınıf ilan etmemi sevmediğinden 'genel'i bırakmak zorunda olmam dışında.
Ali Beadle

Xcode'un genel bir tipte iç içe geçmiş türe izin vermemesi dışında harika çalışıyor ... yani genel bir sınıfınız varsa, yalnızca hesaplanan özellikler mümkün olduğu için umutsuz görünüyor.
BenMQ

19

Dosya kapsamında statik depolama süresi olan değişkenleri bildirmek mümkün görünüyor (C'deki gibi):

var sharedInstance: SplitViewController? = nil

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

mmmh, neden olmasın, ancak dosya kapsamındaki bir var tanımlayın, uzun süreli kullanımda bir bellek sızıntısı yapmaz?
Vincent Saluzzo

@VincentSaluzzo Swift'den önce yaptıklarınızdan hiçbir farkı yok: tek örneği statik bir değişkende saklayın. Süreç kadar uzun süren tek örnek dışında burada sızdırılacak hiçbir şey yok.
Nikolai Ruhe

Bunu oyun parkında kendi sınıfımla denedim. Çalışmıyor çünkü bu "statik" değişkeni başlattığınızda sınıf henüz bildirilmemiştir. Xcode projesinde denemedim (sanırım orada çalışmış olmalı?). Bu nedenle, bir sınıf için protokol belirlerken her zaman yaptığınız gibi "ileri sınıf bildirimi" ni bulmam gerekebilir.
kawingkelvin

2
Xcode 6.0'da, olsalar bile aynı ada sahip iki dosya kapsamı değişkenine sahip olamayacağınızı unutmayın private.
nschum

@NikolayTsenkov Kesinlikle.
Nikolai Ruhe

14

Tercih ettiğim yöntem, sınıfın dışında özel bir dosya kapsamı varlığını kullanmak ve ardından sınıf / statik alıcıları ve ayarlayıcıları uygulamaktır:

private var _classVar: Int = 0;

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

5

Swift 1.2'den itibaren (Xcode 6.3b1 ve sonraki sürümlerde mevcuttur), staticsınıf özellikleri ve yöntemler desteklenmektedir.

class SomeClass
{
    static var someVariable: Int = 0
}

1
classDeğişkeni az önce onaylamadıklarını mı anladınız yoksa bir ayrım var mı (eskiden staticyapılar classiçin, sınıflar için)?
Chris Conover

@chrisco Sürüm notları bunun statictakma adı olduğunu belirtir class final.
Andreas Ley 15


4

Dosya kapsamındaki var'a yeterince benzer ancak daha özelleştirilebilir ve tekil kullanıma yakın bir çözüm, sınıfın özelliği olarak statik var'ı destekleyen bir yapı kullanmaktır.

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

Tamam, işi yapan Nikolai'nin çözümüyle. Değişikliklerimi bilgi için bu ileti dizisine gönderiyorum

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

ve örneğin, appDelegate uygulamamda, bu statik yönteme şu şekilde erişebiliyorum

SplitViewController.sharedInstance()!.presentsWithGesture = false

Merak ediyorum, ama o zaman "örnek" değişkeni genel bir değişken değil mi? Bu, başka bir tekil sınıfınız varsa, değişken "örneğinizin" üzerine yazılacağı anlamına gelir, değil mi?
Raphael

1

Hatadaki ifade, bunun gelecekte bir dil özelliği olacağını büyük ölçüde ima etmektedir.

Geçici olarak Uygulama Temsilcisi'nde bir özellik değişkeni bildirmek ve oradan almak isteyebilirsiniz. İdeal değil, kesinlikle bir anti-model, ancak gerektiğinde geri almanız için size merkezi bir yer sağlar UISplitViewController.


Hayır, çünkü benim durumumda, SplitViewController film şeridinden uyandığında çalışma zamanı tarafından başlatılıyordu, bu yüzden uygulama temsilcimden bu görünüm denetleyicisine doğrudan erişemiyorum
Vincent Saluzzo

1

Sınıf değişkenlerini bir iç yapı değişkeninin içine sarmalısınız

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

Bunu dene:

class var instance: SplitViewController {
    return nil
}

0

Swift'de Tip Mülkiyet olarak adlandırılır .

Tür özelliklerini static anahtar sözcüğüyle tanımlarsınız. Sınıf türleri için hesaplanmış tür özellikleri için, bunun yerine class anahtar sözcüğünü kullanarak alt sınıfların üst sınıfın uygulamasını geçersiz kılmasına izin verebilirsiniz. Aşağıdaki örnek, depolanan ve hesaplanan tür özelliklerinin sözdizimini gösterir:

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

Aşağıdaki bağlantıdan daha fazlasını okuyun,

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.