Переменные класса еще не поддерживаются

93

Я начинаю свой проект с контроллера разделения представления в качестве исходного контроллера представления и запускаю его автоматически из раскадровки.

Как правило, приложение с этим пользовательским интерфейсом имеет один и только один контроллер разделения представления в качестве корневого, поэтому я создаю статическую переменную в подклассе и устанавливаю ее при выполнении инициализации.

Итак, я хочу попробовать это поведение с быстрой скоростью.

Я прочитал руководство по языку программирования Swift в iBook о свойствах типа (с ключевым словом static и class) и пробовал кусок кода для работы:

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 03
Это дает ту же ошибку.
Cezar
1
Это первое семя, успокойся. :) Если в книге написано, что она поддерживается, но еще не доступна, так и будет . Даже ошибка говорит "пока" .
akashivskyy 03
1
Да, @akashivskyy, у вас есть причина, но, возможно, это может быть ошибка с моей стороны, и у кого-то есть решение, как это сделать ...
Винсент Салуццо
1
@lespommes Apple, как известно, хранит молчание обо всем, что ожидается. Им неловко, что в их огромном выпуске нового флагманского языка не хватало такой стандартной и очевидной функции. Прежде чем Swift будет готов к серьезному использованию, необходимо внести множество улучшений.
Hyperbole

Ответы:

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
Как говорит Билл, это не то же самое, но это мне нужно!
Винсент Салуццо
@VincentSaluzzo (и Билл) Какая разница между этой переменной и переменной класса?
Skywinder
Документация Apple недавно изменилась на статус обновления: developer.apple.com/library/ios/documentation/Swift/Conceptual/ ... Фактически,class ключевое слово теперь может использоваться только для вычисляемых свойств, а static - для всех свойств типа (в enum, class или структура)
Винсент Салуццо
@skywinder Как я уже упоминал в своем ответе, истинные переменные класса могут быть унаследованы подклассами. Статические переменные не могут.
Билл
@VincentSaluzzo Обновляет ли Apple свой документ? developer.apple.com/library/ios/documentation/Swift/Conceptual/… посмотрите на четвертый абзац: «Для типов значений (то есть структур и перечислений) вы можете определять свойства сохраненных и вычисляемых типов. Для классов вы можете определять только свойства вычисляемого типа ".
fujianjin6471
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 затем можно использовать, как если бы оно было свойством сохраненного типа.

Glessard
источник
1
Сработало для меня, за исключением того, что мне пришлось отказаться от «общедоступного», поскольку XCode 6.0 не хотел, чтобы я объявлял публичный класс внутри внутреннего класса.
Али Бидл
Отлично работает, за исключением того, что xcode не разрешает вложенный тип в общий тип ... поэтому, если у вас есть общий класс, это кажется довольно безнадежным, поскольку возможны только вычисляемые свойства.
BenMQ
19

Кажется, можно объявить переменные со статической продолжительностью хранения в области файла (как в C):

var sharedInstance: SplitViewController? = nil

class SplitViewController: UISplitViewController {
    ....
    func initialization() {
        sharedInstance = self
    }
}
Николай Рухе
источник
ммм, а почему бы и нет, но определение переменной в области видимости файла не приводит к утечке памяти при длительном использовании?
Винсент Салуццо
@VincentSaluzzo Нет разницы с тем, что вы делали до Swift: сохраните единственный экземпляр в статической переменной. Здесь нечего просачиваться, кроме единственного экземпляра, который живет столько же, сколько и процесс.
Николай Рухе
Я пробовал это на детской площадке со своим классом. Это не работает, потому что класс еще не был объявлен, когда вы инициализировали эту "статическую" переменную. Я не пробовал это в проекте Xcode (думаю, там должно было работать?). Так что мне может потребоваться выяснить «предварительное объявление класса», как вы всегда делаете при указании протокола для класса.
kawingkelvin
2
Обратите внимание, что в Xcode 6.0 у вас не может быть двух переменных области видимости файла с одинаковым именем, даже если они есть private.
nschum
@NikolayTsenkov Ровно.
Николай Рухе
14

Мой предпочтительный метод - просто использовать частную область видимости файла var за пределами класса, а затем реализовать методы получения и установки класса / статики:

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для классов)?
Крис Коновер,
@chrisco В примечаниях к выпуску указано, что staticэто псевдоним для class final.
Андреас Лей,
4

Решение, достаточно похожее, чем var в области видимости файла, но более настраиваемое и близкое к синглтону, - использовать структуру, которая поддерживает статический 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
Винсент Салуццо
источник
Мне просто любопытно, но разве переменная "instance" не является глобальной переменной? Это будет означать, что если у вас есть другой одноэлементный класс, ваша переменная "instance" будет перезаписана, верно?
Рафаэль
1

Формулировка ошибки явно подразумевает, что в будущем это будет языковая функция.

Вы можете временно прибегнуть к объявлению переменной свойства в делегате приложения и получить ее оттуда. Не идеально, определенно анти-паттерн, но даст вам центральное место для извлечения UISplitViewControllerнужного.

Цезарь
источник
Нет, потому что в моем случае SplitViewController был инициализирован во время выполнения, когда просыпался из раскадровки, поэтому я не могу напрямую получить доступ к этому контроллеру представления из моего делегата приложения
Винсент Салуццо
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
}
fxchou123
источник
0

В Swift это называется Type Property .

Вы определяете свойства типа с помощью ключевого слова 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

Мегаполис
источник