Variáveis ​​de classe ainda não suportadas

93

Eu começo meu projeto com um controlador de visualização dividida como controlador de visualização inicial e o inicio automaticamente a partir do storyboard.

Geralmente, um aplicativo com esta IU tem um e apenas um controlador de visualização dividida como root, então eu crio uma variável estática na subclasse e a defino quando a inicialização é feita.

Então, eu quero tentar esse comportamento com o swift.

Eu li o livro do guia da linguagem de programação Swift no iBook sobre propriedades de tipo (com a palavra-chave static e class) e tentei um pedaço de código para o trabalho:

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

mas descobri quando o Xcode diz que a palavra-chave class para propriedades de tipo ainda não era suportada.

detalhe do erro na imagem

Você teve uma solução para fazer isso?

Vincent Saluzzo
fonte
O que acontece se você substituir 'let' por 'var'?
ZunTzu
Isso produz o mesmo erro.
Cezar
1
É a primeira semente, acalme-se. :) Se o livro disser que é compatível e ainda não está disponível, será . Até o erro diz "ainda" .
akashivskyy
1
Sim @akashivskyy você tem razão, mas pode ser que seja um erro da minha parte e alguém tenha uma solução para fazer esse comportamento ...
Vincent Saluzzo
1
@lespommes A Apple é notoriamente calada sobre tudo o que está pendente. É constrangedor para eles que um recurso tão óbvio e padrão não tenha existido em seu grande lançamento de sua nova linguagem principal. Há muitas melhorias necessárias antes que o Swift esteja pronto para uso sério.
Hipérbole de

Respostas:

37

Swift agora tem suporte para variáveis ​​estáticas em classes. Isso não é exatamente o mesmo que uma variável de classe (porque elas não são herdadas por subclasses), mas você chega bem perto:

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

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

X.x = 5

println(X.x)
Conta
fonte
1
Como diz Bill, não é a mesma coisa, mas é o que preciso!
Vincent Saluzzo
@VincentSaluzzo, (e Bill) Qual a diferença entre esta e a variável de classe?
skywinder
A documentação da Apple mudou recentemente para atualizar o status: developer.apple.com/library/ios/documentation/Swift/Conceptual/… Na verdade, a classpalavra-chave só pode ser usada para propriedades computadas agora e estático é para todas as propriedades de tipo (em enum, class ou struct)
Vincent Saluzzo
@skywinder Como mencionei em minha resposta, as verdadeiras variáveis ​​de classe podem ser herdadas por subclasses. Variáveis ​​estáticas não podem.
Bill
@VincentSaluzzo A Apple atualiza seu documento? developer.apple.com/library/ios/documentation/Swift/Conceptual/… olhe para o quarto parágrafo: "Para tipos de valor (ou seja, estruturas e enumerações), você pode definir propriedades de tipo armazenado e calculado. Para classes, você pode definir propriedades de tipo computado apenas. "
fujianjin6471
73

Incorporar uma estrutura pode funcionar perfeitamente como uma solução alternativa:

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

A propriedade de tipo computado SomeClass.workaroundClassVariable pode então ser usada como se fosse uma propriedade de tipo armazenado.

Glessard
fonte
1
Funcionou para mim - exceto quando tive que abandonar o 'público', pois o XCode 6.0 não gostou que eu declarasse uma classe pública dentro de uma classe interna.
Ali Beadle
Funciona muito bem, exceto que o xcode não permite o tipo aninhado em um tipo genérico ... então, se você tem uma classe genérica, parece um tanto inútil, já que apenas propriedades computadas são possíveis.
BenMQ de
19

Parece ser possível declarar variáveis ​​com duração de armazenamento estático no escopo do arquivo (como em C):

var sharedInstance: SplitViewController? = nil

class SplitViewController: UISplitViewController {
    ....
    func initialization() {
        sharedInstance = self
    }
}
Nikolai Ruhe
fonte
mmmh, por que não, mas definir uma var no escopo do arquivo não causa um vazamento de memória em um uso longo?
Vincent Saluzzo
@VincentSaluzzo Não há diferença para o que você fazia antes do Swift: armazene a única instância em uma variável estática. Não há nada a ser vazado aqui, exceto a única instância que dura tanto quanto o processo.
Nikolai Ruhe
Eu tentei isso no playground com minha própria classe. Não funciona porque a classe ainda não foi declarada quando você inicializou aquela var "estática". Eu não tentei no projeto Xcode (eu acho que deve ter funcionado lá?). Portanto, posso precisar descobrir "declaração de encaminhamento de classe" como você sempre faz ao especificar o protocolo para uma classe.
kawingkelvin
2
Observe que no Xcode 6.0, você não pode ter duas variáveis ​​de escopo de arquivo com o mesmo nome, mesmo que sejam private.
nschum
@NikolayTsenkov Exatamente.
Nikolai Ruhe
14

Meu método preferido é apenas usar um escopo de arquivo privado var fora da classe e, em seguida, implementar getters e setters class / static:

private var _classVar: Int = 0;

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

A partir do Swift 1.2 (disponível com o Xcode 6.3b1 e posterior), staticas propriedades e métodos da classe são suportados.

class SomeClass
{
    static var someVariable: Int = 0
}
Andreas Ley
fonte
1
Você percebeu se eles apenas tornaram obsoleta a classvariável ou há uma distinção (costumava ser staticpara structs, classpara classes)?
Chris Conover
@chrisco As notas da versão afirmam que staticé um alias para class final.
Andreas Ley
4

Uma solução bastante semelhante do que var no escopo do arquivo, mas mais personalizável e próxima do singleton, é usar uma estrutura que suporte var estático como propriedade de classe

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

Ok, com a solução do Nikolai que faz o trabalho. Eu posto minhas mudanças neste tópico para informações

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

e por exemplo, em meu appDelegate, posso acessar este método estático como este

SplitViewController.sharedInstance()!.presentsWithGesture = false
Vincent Saluzzo
fonte
Estou apenas curioso, mas a variável "instância" não é uma variável global então? Isso significa que, se você tiver outra classe singleton, sua "instância" da variável será substituída, certo?
Raphael
1

O texto do erro implica fortemente que este será um recurso de idioma no futuro.

Você pode querer recorrer temporariamente à declaração de uma variável de propriedade no Delegado do Aplicativo e recuperá-la de lá. Não é o ideal, definitivamente um antipadrão, mas daria a você um local central para recuperar o UISplitViewControllerquando necessário.

Cezar
fonte
Não porque no meu caso, o SplitViewController foi inicializado pelo tempo de execução quando acordado do storyboard, então não posso acessar diretamente este controlador de visualização do meu delegado de aplicativo
Vincent Saluzzo
1

Você tem que envolver as variáveis ​​de classe dentro de uma variável de estrutura interna

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

Experimente isto:

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

É chamado de propriedade de tipo no Swift.

Você define as propriedades de tipo com a palavra-chave estática. Para propriedades de tipo computado para tipos de classe, você pode usar a palavra-chave class em vez de permitir que as subclasses substituam a implementação da superclasse. O exemplo abaixo mostra a sintaxe para propriedades de tipo armazenado e calculado:

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

Leia mais no link abaixo,

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

Lorem
fonte