Arquivo de constantes globais no Swift

336

Nos meus projetos Objective-C, geralmente uso um arquivo de constantes globais para armazenar itens como chaves e nomes de notificação NSUserDefaults. Parece algo como isto:

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Como faço exatamente a mesma coisa no Swift?

user1028028
fonte
3
Você pode ver isso tutoiral
Anish Parajuli 웃

Respostas:

764

Estruturas como espaço para nome

Na IMO, a melhor maneira de lidar com esse tipo de constantes é criar um Struct.

struct Constants {
    static let someNotification = "TEST"
}

Então, por exemplo, chame assim no seu código:

print(Constants.someNotification)

Aninhamento

Se você deseja uma organização melhor, aconselho o uso de subestruturas segmentadas

struct K {
    struct NotificationKey {
        static let Welcome = "kWelcomeNotif"
    }

    struct Path {
        static let Documents = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
        static let Tmp = NSTemporaryDirectory()
    }
}

Então você pode apenas usar, por exemplo K.Path.Tmp

Exemplo do mundo real

Esta é apenas uma solução técnica, a implementação real no meu código se parece mais com:

struct GraphicColors {

    static let grayDark = UIColor(0.2)
    static let grayUltraDark = UIColor(0.1)

    static let brown  = UIColor(rgb: 126, 99, 89)
    // etc.
}

e


enum Env: String {
    case debug
    case testFlight
    case appStore
}

struct App {
    struct Folders {
        static let documents: NSString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
        static let temporary: NSString = NSTemporaryDirectory() as NSString
    }
    static let version: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
    static let build: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String

    // This is private because the use of 'appConfiguration' is preferred.
    private static let isTestFlight = Bundle.main.appStoreReceiptURL?.lastPathComponent == "sandboxReceipt"

    // This can be used to add debug statements.
    static var isDebug: Bool {
        #if DEBUG
        return true
        #else
        return false
        #endif
    }

    static var env: Env {
        if isDebug {
            return .debug
        } else if isTestFlight {
            return .testFlight
        } else {
            return .appStore
        }
    }
}
Francescu
fonte
123
Pessoalmente, procurei um Constant.swiftarquivo com estruturas separadas, mas não encapsulado em uma grande Constantsestrutura para evitar chamadas muito longas para uma constante. Então eu chamo em NotificationKey.Welcomevez deConstants.NotificationKey.Welcome
Kevin Hirsch
2
@KevinHirsch não é uma má idéia. Por outro lado: se eu tiver o prefixo .Constants, eu sei que não é uma coisa local, mas tipo de no Constantes namespace
brainray
3
@brainray Entendo o seu ponto, mas no meu código, as constantes nunca são locais (sempre em a Constants.swift) e sempre parecem iguais: começando com maiúsculas e com um nome de categoria significativo como "NotificationKey", "SegueIdentifier" ou "Path", .. . Assim eu posso ver facilmente quando é uma constante;)
Kevin Hirsch
15
Isso não é compatível com o código Objective-C (estruturas, nem constantes de nível superior são exportadas para Objective-C).
RndmTsk
3
@VarunNahariastruct Helpers { static func RGBCOLOR(red: Int, green: Int, blue: Int) -> UIColor { return UIColor(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1) } static func IOS7VERSION() -> Bool { return UIDevice.currentDevice().systemVersion.compare("7.0", options: .NumericSearch, range: nil, locale: nil) != .OrderedAscending } }
André Slotta
109

Estou atrasado para a festa.

Não importa como eu gerencio o arquivo de constantes, para que faça mais sentido para os desenvolvedores enquanto escrevia o código rapidamente.

PARA URL:

//URLConstants.swift

  struct APPURL {

    private struct Domains {
        static let Dev = "http://test-dev.cloudapp.net"
        static let UAT = "http://test-UAT.com"
        static let Local = "192.145.1.1"
        static let QA = "testAddress.qa.com"
    }

    private  struct Routes {
        static let Api = "/api/mobile"
    }

    private  static let Domain = Domains.Dev
    private  static let Route = Routes.Api
    private  static let BaseURL = Domain + Route

    static var FacebookLogin: String {
        return BaseURL  + "/auth/facebook"
    }
}

Para CLIENTES:

//FontsConstants.swift
struct FontNames {

    static let LatoName = "Lato"
    struct Lato {
        static let LatoBold = "Lato-Bold"
        static let LatoMedium = "Lato-Medium"
        static let LatoRegular = "Lato-Regular"
        static let LatoExtraBold = "Lato-ExtraBold"
    }
}

PARA TODAS AS CHAVES USADAS NO APP

//KeyConstants.swift
    struct Key {

        static let DeviceType = "iOS"
        struct Beacon{
            static let ONEXUUID = "xxxx-xxxx-xxxx-xxxx"
        }

        struct UserDefaults {
            static let k_App_Running_FirstTime = "userRunningAppFirstTime"
        }

        struct Headers {
            static let Authorization = "Authorization"
            static let ContentType = "Content-Type"
        }
        struct Google{
            static let placesKey = "some key here"//for photos
            static let serverKey = "some key here"
        }

        struct ErrorMessage{
            static let listNotFound = "ERROR_LIST_NOT_FOUND"
            static let validationError = "ERROR_VALIDATION"
        }
    }

PARA CONSTANTES DE CORES:

//ColorConstants.swift
struct AppColor {

    private struct Alphas {
        static let Opaque = CGFloat(1)
        static let SemiOpaque = CGFloat(0.8)
        static let SemiTransparent = CGFloat(0.5)
        static let Transparent = CGFloat(0.3)
    }

    static let appPrimaryColor =  UIColor.white.withAlphaComponent(Alphas.SemiOpaque)
    static let appSecondaryColor =  UIColor.blue.withAlphaComponent(Alphas.Opaque)

    struct TextColors {
        static let Error = AppColor.appSecondaryColor
        static let Success = UIColor(red: 0.1303, green: 0.9915, blue: 0.0233, alpha: Alphas.Opaque) 
    }

    struct TabBarColors{
        static let Selected = UIColor.white
        static let NotSelected = UIColor.black
    }

    struct OverlayColor {
        static let SemiTransparentBlack = UIColor.black.withAlphaComponent(Alphas.Transparent)
        static let SemiOpaque = UIColor.black.withAlphaComponent(Alphas.SemiOpaque)
        static let demoOverlay = UIColor.black.withAlphaComponent(0.6)
    }
}

Você pode agrupar todos esses arquivos em um grupo comum chamado Constants no seu projeto Xcode.

E para mais, assista a este vídeo

Anish Parajuli 웃
fonte
obrigado, achei seu método o mais conveniente (pelo menos para mim), muito bem! 8)
Yatko 8/17
2
melhor do que a minha resposta
Kirit Vaghela
11
Não se esqueça de importar o UIKit :)
alicanbatur 28/03
2
As variáveis ​​estáticas não aumentam o tamanho do aplicativo durante o tempo de execução, pois todas as variáveis ​​estáticas são carregadas quando o aplicativo começa a ser executado?
Anand
11
Eu sei que isso tem mais de um ano, mas só queria dizer que isso é fantástico. Bem feito para compartilhar o conhecimento sobre este 👌🏻
user1898712
28

Embora eu prefira a maneira do @ Francescu (usando uma estrutura com propriedades estáticas), você também pode definir constantes e variáveis ​​globais:

let someNotification = "TEST"

Observe, porém, que diferentemente das variáveis ​​/ constantes locais e das propriedades de classe / estrutura, os globais são implicitamente preguiçosos, o que significa que são inicializados quando são acessados ​​pela primeira vez.

Leitura sugerida: Variáveis ​​globais e locais , e também variáveis ​​globais no Swift não são variáveis

Antonio
fonte
Esta é a maneira correta de declarar as constantes. A abordagem struct é muito boa para facilitar a leitura.
João Nunes
11
Eu não recomendo esta abordagem, uma vez que anula OOP principle..You pode ver isso tutoiral
Anish Parajuli 웃
11
@ThatlazyiOSGuy 웃 Swift é uma linguagem OOP, mas o foco também está na programação funcional (pelo menos, mais conceitos funcionais). Essa é uma maneira perfeitamente válida de declarar constantes, embora ofusque severamente o espaço de nomes String para qualquer IDE.
Dean Kelly
Você diz que a diferença está na preguiça implícita, mas se você usar uma var estática calculada, ela atuará da mesma maneira que um global e despachará uma e apenas uma vez chamada.
Dean Kelly
11
aguarde, mas o problema potencial é que struct é do tipo valor, classe é tipo de referência, a atribuição de instância da classe no struct tornará a classe grosseira no tipo de valor, o que é indesejável?
precisa saber é o seguinte
23

Constant.swift

import Foundation

let kBaseURL = NSURL(string: "http://www.example.com/")

ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)
Kirit Vaghela
fonte
Por que motivo usa o kBaseURL em vez do BASEURL? Obrigado!
Josep Escobar
Provavelmente, ele também está desenvolvendo aplicativos para Android e é um padrão para Android.
Borana
5
Há um padrão para constantes em Objective-C, você sempre vai declará-los usando o seguinte formato: k + camelo nome caso da propriedade
Laur Stefan
20

Considere enumerações. Eles podem ser divididos logicamente para casos de uso separados.

enum UserDefaultsKeys: String {
    case SomeNotification = "aaaaNotification"
    case DeviceToken = "deviceToken"
}

enum PhotoMetaKeys: String {
    case Orientation = "orientation_hv"
    case Size = "size"
    case DateTaken = "date_taken"
}

Um benefício exclusivo ocorre quando você tem uma situação de opções mutuamente exclusivas, como:

for (key, value) in photoConfigurationFile {
    guard let key = PhotoMetaKeys(rawvalue: key) else {
        continue // invalid key, ignore it
    }
    switch (key) {
    case.Orientation: {
        photo.orientation = value
    }
    case.Size: {
        photo.size = value
    }
    }
}

Neste exemplo, você receberá um erro de compilação porque não lidou com o caso de PhotoMetaKeys.DateTaken.

William Entriken
fonte
11
O caso enum não pode conter valores duplicados. Portanto, isso não se encaixa em todos os cenários.
Aaina Jain
@AainaJain Na verdade, se as propriedades computadas forem usadas para os valores em vez do valor bruto da enumeração, é fácil ter casos diferentes da enumeração que produzam o mesmo valor.
future-adam
14

Ou apenas no GlobalConstants.swift:

import Foundation

let someNotification = "aaaaNotification"
ChikabuZ
fonte
8

Como outros já mencionaram, qualquer coisa declarada fora de uma classe é global.

Você também pode criar singletons:

class TestClass {
    static let sharedInstance = TestClass()
    // Anything else goes here
    var number = 0
}

Sempre que você quiser usar algo desta classe, por exemplo, escreva:

TestClass.sharedInstance.number = 1

Se você agora escreve println(TestClass.sharedInstance.number)de qualquer lugar do seu projeto, imprime 1no log. Isso funciona para todos os tipos de objetos.

tl; dr: sempre que você quiser tornar tudo em uma classe global, adicionar static let sharedInstance = YourClassName()à classe e endereçar todos os valores da classe com o prefixoYourClassName.sharedInstance

Jacob R
fonte
uma pergunta para voce. outras respostas envolvem o uso de struct para armazenar informações, mas o problema em potencial é que struct é um tipo de valor, classe é um tipo de referência; atribuir uma instância de classe em struct irá classificar a classe como tipo de valor, o que é indesejável, certo?
precisa saber é o seguinte
5

O que fiz no meu projeto Swift
1: Criar um novo arquivo Swift
2: Crie uma estrutura e uma constante estática nele.
3: Para usar, use YourStructName.baseURL

Nota: Após a criação da inicialização, leva pouco tempo para que seja exibida em outros controladores de exibição após 2-5 segundos.

import Foundation

    struct YourStructName {
    static let MerchantID = "XXX"
    static let MerchantUsername = "XXXXX"
    static let ImageBaseURL = "XXXXXXX"
    static let baseURL = "XXXXXXX"
    }
Vinay Krishna Gupta
fonte
3

Para notificações, você pode usar a extensão, algo como isto:

extension Notification.Name {
    static let testNotification = "kTestNotification"
}

E use-o como NotificationCenter.default.post(name: .testNotification, object: nil)

B. Sapato
fonte
2

Para ter constantes globais em meus aplicativos, é isso que faço em um arquivo Swift separado :

import Foundation

struct Config {
    static let baseURL = "https://api.com"

    static APIKeys {
        static let token = "token"
        static let user = "user"
    }

    struct Notifications {
        static let awareUser = "aware_user"
    }
}

É fácil de usar e ligar para qualquer lugar como este:

print(Config.Notifications.awareUser)
Ale Mohamad
fonte
1

Cores

extension UIColor {
    static var greenLaPalma: UIColor {
        return UIColor(red:0.28, green:0.56, blue:0.22, alpha:1.00)
    }
}

Fontes

enum CustomFontType: String {
    case avenirNextRegular = "AvenirNext-Regular",
    avenirDemiBold = "AvenirNext-DemiBold"
}

extension UIFont {
    static func getFont(with type: CustomFontType, size: CGFloat) -> UIFont {
        let font = UIFont(name: type.rawValue, size: size)!

        return font
    }
}

Para outros - tudo o mesmo que na resposta aceita.

Bohdan Savych
fonte
1

De acordo com os documentos rápidos, as variáveis ​​globais são declaradas no escopo do arquivo.

Variáveis ​​globais são variáveis ​​definidas fora de qualquer contexto de função, método, fechamento ou tipo

Basta criar um arquivo rápido (por exemplo: Constnats.swift) e declarar suas constantes lá:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"

e chame-o de qualquer lugar do seu projeto, sem a necessidade de mencionar struct, enum ou nome da classe.

// MyViewController.swift

NotificationCenter.default.post(name: SOME_NOTIF, object: nil)

Eu acho que isso é muito melhor para a legibilidade do código.

Seif Meddeb
fonte
1

Versão Swift 4

Se você deseja criar um nome para o NotificationCenter:

extension Notification.Name {
    static let updateDataList1 = Notification.Name("updateDataList1")
}

Assine as notificações:

NotificationCenter.default.addObserver(self, selector: #selector(youFunction), name: .updateDataList1, object: nil)

Enviar notificação:

NotificationCenter.default.post(name: .updateDataList1, object: nil)

Se você quer apenas uma classe com variáveis ​​para usar:

class Keys {
    static let key1 = "YOU_KEY"
    static let key2 = "YOU_KEY"
}

Ou:

struct Keys {
    static let key1 = "YOU_KEY"
    static let key2 = "YOU_KEY"
}
Valeriy
fonte
1

Enums sem caixa também podem ser usados.

Vantagem - Eles não podem ser instanciados.

enum API {
    enum Endpoint {
        static let url1 = "url1"
        static let url2 = "url2"
    }
    enum BaseURL {
        static let dev = "dev"
        static let prod = "prod"
    }
}
Pranav Pravakar
fonte
0

Aprenda com a Apple é a melhor maneira.

Por exemplo, a notificação do teclado da Apple:

extension UIResponder {

    public class let keyboardWillShowNotification: NSNotification.Name

    public class let keyboardDidShowNotification: NSNotification.Name

    public class let keyboardWillHideNotification: NSNotification.Name

    public class let keyboardDidHideNotification: NSNotification.Name

}

Agora eu aprendo com a Apple:

extension User {
    /// user did login notification
    static let userDidLogInNotification = Notification.Name(rawValue: "User.userDidLogInNotification")
}

Além do mais NSAttributedString.Key.foregroundColor:

extension NSAttributedString {

    public struct Key : Hashable, Equatable, RawRepresentable {

        public init(_ rawValue: String)

        public init(rawValue: String)
    }
}

extension NSAttributedString.Key {

    /************************ Attributes ************************/

    @available(iOS 6.0, *)
    public static let foregroundColor: NSAttributedString.Key // UIColor, default blackColor

}

Agora eu aprendo da Apple:

extension UIFont {

    struct Name {

    }

}

extension UIFont.Name {

    static let SFProText_Heavy = "SFProText-Heavy"
    static let SFProText_LightItalic = "SFProText-LightItalic"
    static let SFProText_HeavyItalic = "SFProText-HeavyItalic"

}

uso:

let font = UIFont.init(name: UIFont.Name.SFProText_Heavy, size: 20)

Aprenda com a Apple é a maneira que todos podem fazer e promover facilmente a qualidade do seu código.

无 夜 之
fonte