Variabel kelas belum didukung

93

Saya memulai proyek saya dengan pengontrol tampilan terpisah sebagai pengontrol tampilan awal dan memulainya secara otomatis dari storyboard.

Umumnya, aplikasi dengan UI ini memiliki satu dan hanya satu pengontrol tampilan terpisah sebagai root, jadi saya membuat variabel statis di subkelas dan menyetelnya saat inisialisasi selesai.

Jadi saya ingin mencoba perilaku ini dengan sigap.

Saya membaca buku panduan bahasa pemrograman Swift di iBook tentang properti Type (dengan kata kunci statis dan kelas) dan mencoba sepotong kode untuk pekerjaan itu:

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

tapi saya tahu ketika Xcode mengatakan kata kunci kelas untuk properti tipe belum didukung.

detail kesalahan pada gambar

Apakah Anda punya solusi untuk melakukan ini?

Vincent Saluzzo
sumber
Apa yang terjadi jika Anda mengganti 'let' dengan 'var'?
ZunTzu
Ini menghasilkan kesalahan yang sama.
Cezar
1
Ini benih pertama, tenanglah. :) Jika buku mengatakan itu didukung dan itu belum tersedia, itu akan terjadi. Bahkan kesalahannya mengatakan "belum" .
akashivskyy
1
Ya @akashivskyy Anda punya alasan tetapi mungkin itu bisa jadi dan kesalahan di pihak saya dan seseorang memiliki solusi untuk melakukan perilaku ini ...
Vincent Saluzzo
1
@lespommes Apple terkenal bungkam tentang apa pun yang tertunda. Sangat memalukan bagi mereka bahwa fitur standar dan jelas kurang dari rilis besar bahasa andalan baru mereka. Ada banyak perbaikan yang diperlukan sebelum Swift siap digunakan secara serius.
Hiperbola

Jawaban:

37

Swift sekarang memiliki dukungan untuk variabel statis di kelas. Ini tidak persis sama dengan variabel kelas (karena mereka tidak diwarisi oleh subkelas), tetapi ini membuat Anda cukup dekat:

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

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

X.x = 5

println(X.x)
Tagihan
sumber
1
Seperti yang dikatakan Bill, itu tidak sama tapi itulah yang saya butuhkan!
Vincent Saluzzo
@VincentSaluzzo, (dan Bill) Apa perbedaan antara variabel ini dan kelas?
skywinder
Dokumentasi Apple telah berubah baru-baru ini ke status pembaruan: developer.apple.com/library/ios/documentation/Swift/Conceptual/… Faktanya, classkata kunci hanya dapat digunakan untuk properti yang dihitung sekarang dan statis untuk semua jenis properti (dalam enum, kelas atau struct)
Vincent Saluzzo
@skywinder Seperti yang saya sebutkan dalam jawaban saya, variabel kelas yang benar dapat diwarisi oleh subkelas. Variabel statis tidak bisa.
Tagihan
@VincentSaluzzo Apakah Apple memperbarui dokumennya? developer.apple.com/library/ios/documentation/Swift/Conceptual/… lihat paragraf keempat: "Untuk tipe nilai (yaitu, struktur dan enumerasi), Anda dapat menentukan properti tipe yang disimpan dan dihitung. Untuk kelas, Anda dapat definisikan properti tipe yang dihitung saja. "
fujianjin6471
73

Menyematkan struct dapat berfungsi dengan baik sebagai solusi:

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

Properti tipe komputasi SomeClass.workaroundClassVariable kemudian dapat digunakan seolah-olah itu adalah properti tipe tersimpan.

glessard
sumber
1
Bekerja untuk saya - kecuali karena saya harus melepaskan 'publik' karena XCode 6.0 tidak menyukai saya mendeklarasikan kelas publik dalam kelas internal.
Ali Beadle
Berfungsi dengan baik, kecuali bahwa xcode tidak mengizinkan tipe bersarang dalam tipe generik ... jadi jika Anda memiliki kelas generik, tampaknya tidak ada harapan karena hanya properti yang dihitung yang memungkinkan.
BenMQ
19

Tampaknya dimungkinkan untuk mendeklarasikan variabel dengan durasi penyimpanan statis dalam cakupan file (seperti di C):

var sharedInstance: SplitViewController? = nil

class SplitViewController: UISplitViewController {
    ....
    func initialization() {
        sharedInstance = self
    }
}
Nikolai Ruhe
sumber
mmmh, mengapa tidak, tetapi mendefinisikan var pada ruang lingkup file tidak melakukan kebocoran memori dalam penggunaan waktu yang lama?
Vincent Saluzzo
@VincentSaluzzo Tidak ada perbedaan dengan apa yang Anda lakukan sebelum Swift: simpan satu-satunya contoh dalam variabel statis. Tidak ada yang bocor di sini, kecuali satu contoh yang hidup selama prosesnya.
Nikolai Ruhe
Saya mencoba ini di taman bermain dengan kelas saya sendiri. Ini tidak berfungsi karena kelas belum dideklarasikan ketika Anda menginisialisasi var "statis" itu. Saya belum mencobanya di proyek Xcode (saya kira itu pasti berfungsi di sana?). Jadi saya mungkin perlu mencari tahu "deklarasi maju kelas" seperti yang selalu Anda lakukan saat menentukan protokol untuk kelas.
kawingkelvin
2
Perhatikan bahwa di Xcode 6.0, Anda tidak dapat memiliki dua variabel cakupan file dengan nama yang sama, meskipun nama tersebut sama private.
nschum
@NikolayTsen.
Nikolai Ruhe
14

Metode pilihan saya adalah dengan hanya menggunakan var cakupan file pribadi di luar kelas dan kemudian menerapkan getter dan setter kelas / statis:

private var _classVar: Int = 0;

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

Mulai Swift 1.2 (tersedia dengan Xcode 6.3b1 dan seterusnya), staticproperti dan metode kelas didukung.

class SomeClass
{
    static var someVariable: Int = 0
}
Andreas Ley
sumber
1
Apakah Anda mengetahui jika mereka tidak lagi menggunakan classvariabel, atau apakah ada perbedaan (dulu staticuntuk struct, classuntuk kelas)?
Chris Conover
@chrisco Catatan rilis menyatakan bahwa staticmerupakan alias untuk class final.
Andreas Ley
4

Solusi yang cukup mirip dengan var dalam cakupan file tetapi lebih dapat disesuaikan dan hampir tunggal adalah dengan menggunakan struct yang mendukung var statis sebagai properti kelas

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

Oke, dengan solusi Nikolai yang melakukan pekerjaan itu. Saya memposting perubahan saya di utas ini untuk informasi

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

dan misalnya, di appDelegate saya, saya dapat mengakses metode statis seperti ini

SplitViewController.sharedInstance()!.presentsWithGesture = false
Vincent Saluzzo
sumber
Saya hanya ingin tahu, tapi bukankah variabel "instance" adalah variabel global? Ini berarti bahwa jika Anda memiliki kelas tunggal lain variabel "instance" Anda akan ditimpa, bukan?
Raphael
1

Kata-kata dalam kesalahan sangat menyiratkan bahwa ini akan menjadi fitur bahasa di masa mendatang.

Anda mungkin ingin menggunakan untuk sementara waktu untuk mendeklarasikan variabel properti di Delegasi Aplikasi dan mengambilnya dari sana. Tidak ideal, pasti anti-pola, tapi akan memberi Anda tempat sentral untuk mengambilnya UISplitViewControllersaat dibutuhkan.

Cezar
sumber
Tidak, karena dalam kasus saya, SplitViewController diinisialisasi oleh runtime saat bangun dari storyboard, jadi saya tidak dapat langsung mengakses pengontrol tampilan ini dari delegasi aplikasi saya
Vincent Saluzzo
1

Anda harus membungkus variabel kelas di dalam variabel struct dalam

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

Coba ini:

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

Ini disebut Type Property di Swift.

Anda menentukan properti tipe dengan kata kunci statis. Untuk properti tipe yang dihitung untuk tipe kelas, Anda bisa menggunakan kata kunci kelas sebagai gantinya untuk mengizinkan subkelas mengganti implementasi superclass. Contoh di bawah ini menunjukkan sintaks untuk properti tipe yang disimpan dan dihitung:

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

Baca lebih lanjut di tautan di bawah ini,

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

Lorem
sumber