クラス変数はまだサポートされていません


93

最初のビューコントローラーとして分割ビューコントローラーを使用してプロジェクトを開始し、ストーリーボードから自動的に開始します。

一般に、このUIを備えたアプリにはルートとして1つだけの分割ビューコントローラーがあるため、サブクラスで静的変数を作成し、初期化が行われたときにそれを設定します。

だから私はこの行動を迅速に試してみたい。

Typeプロパティ(静的およびクラスキーワードを使用)についてiBookでSwiftプログラミング言語ガイドブックを読み、ジョブにコードの一部を試します。

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

しかし、Xcodeがタイププロパティのクラスキーワードがまだサポートされていないと言ったとき、私は理解しました。

画像のエラー詳細

これを行うための解決策はありましたか?


「let」を「var」に置き換えるとどうなりますか?
ZunTzu 2014年

同じエラーが発生します。
Cezar

1
落ち着いて最初の種です。:)本がそれがサポートされていると言い、それまだ利用可能でない場合、それサポートされます。エラーでさえ「まだ」と言ってます。
akashivskyy 14年

1
はい@akashivskyyあなたは理由がありますが、それは私の側のエラーであり、誰かがこの動作を行うための解決策を持っている可能性があります...
Vincent Saluzzo

1
@lespommes Appleは、未解決の問題について悪名高く知られております。新しい旗艦言語の巨大なリリースから、そのような標準的で明白な機能が欠けていたことは彼らにとって恥ずかしいことです。Swiftを本格的に使用する前に、多くの改善が必要です。
双曲線2015

回答:


37

Swiftはクラスの静的変数をサポートするようになりました。これはクラス変数とまったく同じではありませんが(サブクラスによって継承されないため)、かなり近づきます。

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
ビルが言うように、それは同じではありませんが、それが必要です!
Vincent Saluzzo

@VincentSaluzzo(およびBill)これとクラス変数の違いは何ですか?
スカイワインダー

Appleのドキュメントが最近更新され、ステータスが更新されました:developer.apple.com/library/ios/documentation/Swift/Conceptual/… 実際、classキーワードは現在、計算されたプロパティにのみ使用でき、静的はすべてのタイププロパティ(列挙型、クラス)またはstruct)
Vincent Saluzzo

@skywinder回答で述べたように、真のクラス変数はサブクラスによって継承できます。静的変数はできません。
ビル

@VincentSaluzzoアップルはそのドキュメントを更新しますか?developer.apple.com/library/ios/documentation/Swift/Conceptual/…4番目の段落を見てください。「値の型(つまり、構造体と列挙型)の場合、格納および計算された型のプロパティを定義できます。クラスの場合は、計算タイプのプロパティのみを定義してください。」
fujianjin6471 2015

73

構造体の埋め込みは、回避策としてうまく機能します。

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計算タイププロパティを、格納されたタイププロパティのように使用できます。


1
XCode 6.0が内部クラス内でパブリッククラスを宣言するのを好まなかったため、「パブリック」を削除する必要があったことを除いて、私のために働きました。
Ali Beadle 2014年

xcodeがジェネリック型でネストされた型を許可しないことを除いて、うまく機能します...ジェネリッククラスがある場合、計算されたプロパティのみが可能であるため、それはかなり絶望的です。
BenMQ、2015年

19

(Cのように)ファイルスコープで静的ストレージ期間を持つ変数を宣言することが可能であるようです:

var sharedInstance: SplitViewController? = nil

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

mmmh、なぜそうではありませんが、varをファイルスコープで定義しても、長時間の使用でメモリリークが発生しませんか?
Vincent Saluzzo 2014年

@VincentSaluzzo Swift以前に行ったことと何の違いもありません:唯一のインスタンスを静的変数に格納します。プロセスの間存続する単一のインスタンスを除いて、ここでリークされるものは何もありません。
ニコライルーエ2014年

私は自分のクラスで遊び場でこれを試しました。「静的」変数を初期化したときにクラスがまだ宣言されていないため、機能しません。私はXcodeプロジェクトでそれを試していません(私はそれがそこで働いたに違いないと思いますか?)。したがって、クラスのプロトコルを指定するときにいつも行うように、「クラス転送宣言」を理解する必要があるかもしれません。
kawingkelvin 2014

2
Xcode 6.0では、たとえ同じであっても、同じ名前の2つのファイルスコープ変数を持つことはできませんprivate
nschum 2014

@NikolayTsenkovその通りです。
ニコライルーエ2014年

14

私が好む方法は、クラスの外部でプライベートファイルスコープの変数を使用し、クラス/静的ゲッターとセッターを実装することです。

private var _classVar: Int = 0;

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

5

Swift 1.2(Xcode 6.3b1以降で利用可能)以降、staticクラスのプロパティとメソッドがサポートされています。

class SomeClass
{
    static var someVariable: Int = 0
}

1
それらがclass変数を非推奨にしただけなのか、それとも(static構造体やclassクラスに使用されていた)違いがあるのか、わかりましたか?
Chris Conover

@chriscoリリースノートにstaticは、のエイリアスであると記載されていclass finalます。
Andreas Ley


4

ファイルスコープはvarに十分似ていますが、よりカスタマイズ可能でほぼシングルトンのソリューションは、クラスのプロパティとして静的変数をサポートする構造体を使用することです。

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

さて、仕事をするニコライの解決策で。情報を得るために、このスレッドに自分の変更を投稿します

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

たとえば、私のappDelegateでは、次のようにこの静的メソッドにアクセスできます

SplitViewController.sharedInstance()!.presentsWithGesture = false

気になるのですが、変数「インスタンス」はグローバル変数ではありませんか?これは、別のシングルトンクラスがある場合、変数「インスタンス」が上書きされることを意味しますよね?
Raphael 14

1

エラーの表現は、これが将来の言語機能になることを強く意味します。

一時的に、アプリケーションデリゲートでプロパティ変数を宣言し、そこから取得することをお勧めします。理想的ではありませんが、間違いなくアンチパターンですがUISplitViewController、必要なときに取得するための中心的な場所になります。


私の場合、SplitViewControllerはストーリーボードから起動したときにランタイムによって初期化されていたため、アプリケーションデリゲートからこのビューコントローラーに直接アクセスできませんでした
Vincent Saluzzo

1

内部の構造体変数内にクラス変数をラップする必要があります

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

これを試して:

class var instance: SplitViewController {
    return nil
}

0

SwiftではTypeプロパティと呼ばれます。

タイププロパティはstaticキーワードで定義します。クラスタイプの計算タイププロパティの場合、代わりにclassキーワードを使用して、サブクラスがスーパークラスの実装をオーバーライドできるようにすることができます。以下の例は、格納および計算された型プロパティの構文を示しています。

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

以下のリンクで詳細を読んでください、

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.