Globale Konstantendatei in Swift


336

In meinen Objective-C-Projekten verwende ich häufig eine globale Konstantendatei, um Dinge wie Benachrichtigungsnamen und Schlüssel für zu speichern NSUserDefaults. Es sieht ungefähr so ​​aus:

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Wie mache ich genau das gleiche in Swift?


3
Sie können dieses Tutoiral sehen
Anish Parajuli 웃

Antworten:


763

Strukturen als Namespace

IMO Der beste Weg, um mit dieser Art von Konstanten umzugehen, besteht darin, eine Struktur zu erstellen.

struct Constants {
    static let someNotification = "TEST"
}

Nennen Sie es dann zum Beispiel in Ihrem Code so:

print(Constants.someNotification)

Nisten

Wenn Sie eine bessere Organisation wünschen, empfehle ich Ihnen, segmentierte Unterstrukturen zu verwenden

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

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

Dann können Sie zum Beispiel einfach verwenden K.Path.Tmp

Beispiel aus der realen Welt

Dies ist nur eine technische Lösung. Die eigentliche Implementierung in meinem Code sieht eher so aus:

struct GraphicColors {

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

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

und


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

123
Persönlich habe ich mich für eine Constant.swiftDatei mit getrennten Strukturen entschieden, die jedoch nicht in einer großen ConstantsStruktur gekapselt ist , um einen zu langen Aufruf einer Konstanten zu vermeiden. Also rufe ich NotificationKey.WelcomestattConstants.NotificationKey.Welcome
Kevin Hirsch

2
@ KevinHirsch keine schlechte Idee. Auf der anderen Seite: Wenn ich das Präfix .Constants habe, weiß ich, dass es keine lokale Sache ist, sondern irgendwie im Namespace Constants
brainray

3
@brainray Ich verstehe Ihren Standpunkt, aber in meinem Code sind Konstanten niemals lokal (immer in a Constants.swift) und sehen immer gleich aus: beginnend mit Großbuchstaben und mit einem aussagekräftigen Kategorienamen wie "NotificationKey", "SegueIdentifier" oder "Path", .. So kann ich leicht sehen, wann es eine Konstante ist;)
Kevin Hirsch

15
Dies ist nicht mit Objective-C-Code kompatibel (Strukturen oder Konstanten der obersten Ebene werden für Objective-C exportiert).
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

Ich bin etwas spät zur Party.

Egal, wie ich die Konstantendatei so verwalte, dass es für Entwickler sinnvoller ist, Code schnell zu schreiben.

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

Für BENUTZERDEFINIERTE:

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

FÜR ALLE IN APP VERWENDETEN SCHLÜSSEL

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

FÜR FARBKONSTANTEN:

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

Sie können diese alle Dateien in eine gemeinsame Gruppe mit dem Namen einschließen Konstanten in Ihrem Xcode-Projekt einschließen.

Und für mehr sehen Sie dieses Video


danke, ich fand deine Methode die bequemste (zumindest für mich), gut gemacht! 8)
Yatko

2
besser als meine Antwort
Kirit Vaghela

1
Vergessen Sie nicht, UIKit zu importieren :)
alicanbatur

2
Erhöhen statische Variablen nicht die Größe der App zur Laufzeit, da alle statischen Variablen geladen werden, wenn die App gestartet wird?
Anand

1
Ich weiß, dass dies über ein Jahr alt ist, wollte aber nur sagen, dass dies fantastisch ist. Gut gemacht für das Teilen des Wissens über dieses user
user1898712

28

Obwohl ich @ Francescus Weg bevorzuge (unter Verwendung einer Struktur mit statischen Eigenschaften), können Sie auch globale Konstanten und Variablen definieren:

let someNotification = "TEST"

Beachten Sie jedoch, dass Globals anders als lokale Variablen / Konstanten und Klassen- / Struktureigenschaften implizit faul sind, was bedeutet, dass sie beim ersten Zugriff initialisiert werden.

Empfohlene Lektüre: Globale und lokale Variablen sowie globale Variablen in Swift sind keine Variablen


Dies ist der richtige Weg, um die Konstanten zu deklarieren. Der Strukturansatz ist sehr gut für die Lesbarkeit.
João Nunes

1
Ich empfehle diesen Ansatz nicht, da er das OOP-Prinzip ungültig
macht. Sie

1
@ThatlazyiOSGuy 웃 Swift ist eine OOP-Sprache, aber der Fokus liegt auch mehr auf funktionaler Programmierung (zumindest mehr funktionale Konzepte). Dies ist eine absolut gültige Methode zum Deklarieren von Konstanten, obwohl der String-Namespace für jede IDE stark getrübt wird.
Dean Kelly

Sie sagen, der Unterschied liegt in der impliziten Faulheit, aber wenn Sie eine berechnete statische Variable verwenden, verhält sie sich genauso wie ein globaler und versendet einmal und nur einmal aufgerufen.
Dean Kelly

1
Warten Sie, aber das potenzielle Problem ist, dass struct ein Werttyp ist, class ein Referenztyp ist. Wenn Sie eine Klasseninstanz in struct zuweisen, wird die Klasse grob in einen Werttyp umgewandelt, was unerwünscht ist.
Martian2049

23

Constant.swift

import Foundation

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

ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

Aus welchem ​​Grund wird kBaseURL anstelle von BASEURL verwendet? Vielen Dank!
Josep Escobar

Wahrscheinlich entwickelt er auch Android-Anwendungen und es ist ein Android-Standard.
BoranA

5
Es gibt ein Muster für Konstanten in Objective-C, Sie werden sie immer im nächsten Format deklarieren: k + Kamel Fallname der Eigenschaft
Laur Stefan

20

Betrachten Sie Aufzählungen. Diese können für separate Anwendungsfälle logisch aufgeteilt werden.

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

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

Ein einzigartiger Vorteil ergibt sich, wenn Sie sich gegenseitig ausschließende Optionen haben, wie z.

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

In diesem Beispiel wird ein Kompilierungsfehler angezeigt, da Sie den Fall von nicht behandelt haben PhotoMetaKeys.DateTaken.


1
Enum case kann keine doppelten Werte enthalten. Das passt also nicht in alle Szenarien.
Aaina Jain

@AainaJain Wenn berechnete Eigenschaften für die Werte anstelle des Enum-Rohwerts verwendet werden, ist es tatsächlich einfach, dass verschiedene Enum-Fälle denselben Wert ausgeben.
Future-Adam

14

Oder einfach in GlobalConstants.swift:

import Foundation

let someNotification = "aaaaNotification"

8

Wie andere bereits erwähnt haben, ist alles, was außerhalb einer Klasse deklariert wird, global.

Sie können auch Singletons erstellen:

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

Wann immer Sie etwas aus dieser Klasse verwenden möchten, schreiben Sie zB:

TestClass.sharedInstance.number = 1

Wenn Sie jetzt println(TestClass.sharedInstance.number)von einer beliebigen Stelle in Ihrem Projekt aus schreiben, werden Sie drucken1 in das Protokoll . Dies funktioniert für alle Arten von Objekten.

tl; dr: Wenn Sie alles in einer Klasse global machen möchten, fügen Sie static let sharedInstance = YourClassName()es der Klasse hinzu und adressieren Sie alle Werte der Klasse mit dem PräfixYourClassName.sharedInstance


eine Frage für dich. Andere Antworten beinhalten die Verwendung von struct zum Speichern von Informationen. Das potenzielle Problem besteht jedoch darin, dass struct ein Werttyp und eine Klasse ein Referenztyp ist. Wenn Sie eine Klasseninstanz in struct zuweisen, wird die Klasse grob in einen Werttyp eingeteilt, was unerwünscht ist, oder?
Martian2049

5

Was ich in meinem Swift-Projekt
1 getan habe : Neue Swift-Datei
erstellen 2: Erstellen Sie eine Struktur und eine statische Konstante darin.
3: Verwenden Sie zur Verwendung einfach YourStructName.baseURL

Hinweis: Nach dem Erstellen dauert die Initialisierung nur wenig, sodass sie nach 2-5 Sekunden in anderen Ansichtssteuerungen angezeigt wird.

import Foundation

    struct YourStructName {
    static let MerchantID = "XXX"
    static let MerchantUsername = "XXXXX"
    static let ImageBaseURL = "XXXXXXX"
    static let baseURL = "XXXXXXX"
    }

3

Für Benachrichtigungen können Sie eine Erweiterung wie die folgende verwenden:

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

Und benutze es gerne NotificationCenter.default.post(name: .testNotification, object: nil)


2

Um globale Konstanten in meinen Apps zu haben, gehe ich wie folgt in einer separaten Swift- Datei vor:

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

Es ist einfach zu bedienen und überall so anzurufen:

print(Config.Notifications.awareUser)

1

Farben

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

Schriftarten

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

Für andere - alles das gleiche wie in der akzeptierten Antwort.


1

Gemäß den schnellen Dokumenten werden globale Variablen im Dateibereich deklariert.

Globale Variablen sind Variablen, die außerhalb von Funktionen, Methoden, Abschlüssen oder Typkontexten definiert werden

Erstellen Sie einfach eine schnelle Datei (zB: Constnats.swift) und deklarieren Sie dort Ihre Konstanten:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"

und rufen Sie es von überall in Ihrem Projekt auf, ohne Struktur, Enumeration oder Klassennamen angeben zu müssen.

// MyViewController.swift

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

Ich denke, dies ist viel besser für die Lesbarkeit des Codes.


1

Swift 4 Version

Wenn Sie einen Namen für NotificationCenter erstellen möchten:

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

Benachrichtigungen abonnieren:

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

Benachrichtigung senden:

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

Wenn Sie nur eine Klasse mit Variablen verwenden möchten:

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

Oder:

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

1

Caseless Enums können ebenfalls verwendet werden.

Vorteil - Sie können nicht instanziiert werden.

enum API {
    enum Endpoint {
        static let url1 = "url1"
        static let url2 = "url2"
    }
    enum BaseURL {
        static let dev = "dev"
        static let prod = "prod"
    }
}

0

Von Apple lernen ist der beste Weg.

Beispiel: Apples Tastaturbenachrichtigung:

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

}

Jetzt lerne ich von Apple:

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

Was ist mehr 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

}

Jetzt lerne ich von 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"

}

Verwendungszweck:

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

Von Apple lernen ist die Art und Weise, wie jeder Ihre Codequalität auf einfache Weise verbessern kann.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.