Файл глобальных констант в Swift


336

В моих проектах Objective-C я часто использую файл глобальных констант для хранения таких вещей, как имена уведомлений и ключи NSUserDefaults. Это выглядит примерно так:

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Как мне сделать то же самое в Swift?


3
Вы можете увидеть это тутоирал
— Аниш Параджули 웃

Ответы:


765

Структуры как пространство имен

ИМО лучший способ справиться с этим типом констант - это создать Struct.

struct Constants {
    static let someNotification = "TEST"
}

Затем, например, назовите это так в своем коде:

print(Constants.someNotification)

гнездование

Если вы хотите лучшую организацию, я советую вам использовать сегментированные подструктуры

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

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

Тогда вы можете просто использовать, например, K.Path.Tmp

Пример из реального мира

Это всего лишь техническое решение, фактическая реализация в моем коде больше похожа на:

struct GraphicColors {

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

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

и


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
Лично я пошел за Constant.swiftфайлом с разделенными структурами, но не инкапсулированным в большую Constantsструктуру, чтобы избежать слишком длинного вызова константы. Поэтому я звоню NotificationKey.WelcomeвместоConstants.NotificationKey.Welcome
— Кевин Хирш

2
@KevinHirsch неплохая идея. С другой стороны: если у меня есть префикс .Constants, я знаю, что это не локальная вещь, а своего рода в пространстве имен Constants
— brainray

3
@brainray Я понимаю вашу точку зрения, но в моем коде константы никогда не являются локальными (всегда в a Constants.swift) и всегда выглядят одинаково: начиная с прописных букв и с содержательным именем категории, таким как «NotificationKey», «SegueIdentifier» или «Path», .. Так что я легко вижу, когда это константа;)
— Кевин Хирш

15
Это несовместимо с кодом Objective-C (структуры и константы верхнего уровня не экспортируются для 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 } }
— Андре Слотта

109

Я опаздываю на вечеринку.

Неважно, как я управляю файлом констант, чтобы он был более понятным для разработчиков при написании кода на языке swift.

ДЛЯ 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"
    }
}

Для пользовательских:

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

Для всех ключей, используемых в приложении

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

ДЛЯ ЦВЕТНЫХ КОНСТАНТ:

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

Вы можете обернуть все эти файлы в общую группу с именем Constants в вашем проекте XCode.

И еще смотреть это видео


спасибо, я нашел ваш метод наиболее удобным (по крайней мере для меня), молодец! 8)
— Ятко

2
лучше, чем мой ответ
— Кирит Вагела

1
Не забудьте импортировать UIKit :)
— alicanbatur

2
Разве статические переменные не увеличивают размер приложения во время выполнения, так как все статические переменные загружаются при запуске приложения?
— Ананд

1
Я знаю, что этому больше года, но просто хотел сказать, что это фантастика. Молодцы за то, что поделились знаниями об этом 👌🏻
— user1898712

28

Хотя я предпочитаю способ @ Francescu (используя структуру со статическими свойствами), вы также можете определить глобальные константы и переменные:

let someNotification = "TEST"

Однако обратите внимание, что в отличие от локальных переменных / констант и свойств класса / структуры глобальные переменные неявно ленивы, что означает, что они инициализируются при первом обращении к ним.

Предлагаемое чтение: глобальные и локальные переменные , а также глобальные переменные в Swift не являются переменными


Это правильный способ объявить константы. Структурный подход очень хорош для удобства чтения.
— Жоау Нуньес

1
Я не рекомендую этот подход , поскольку он аннулирует OOP principle..You могут видеть эту tutoiral
— Аниш Parajuli 웃

1
@ThatlazyiOSGuy 웃 Swift - язык ООП, но больше внимания уделяется функциональному программированию (по крайней мере, более функциональным концепциям). Это совершенно правильный способ объявления констант, хотя он сильно затуманивает пространство имен String для любой IDE.
— Дин Келли

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

1
подождите, но потенциальная проблема заключается в том, что структура является типом значения, класс является ссылочным типом, назначение экземпляра класса в структуре приведет к грубому обращению класса в тип значения, что нежелательно ??
— Martian2049

23

Constant.swift

import Foundation

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

ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

По какой причине использует kBaseURL вместо BASEURL? Спасибо!
— Хосеп Эскобар

Вероятно, он также разрабатывает приложения для Android, и это стандарт Android.
— BoranA

5
В Objective-C есть шаблон для констант, вы всегда будете объявлять их, используя следующий формат: k + верблюд имя свойства
— Laur Stefan

20

Рассмотрим перечисления. Они могут быть логически разбиты на отдельные варианты использования.

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

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

Одно уникальное преимущество происходит, когда у вас есть ситуация взаимоисключающих опций, таких как:

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

В этом примере вы получите ошибку компиляции, потому что вы не обработали случай PhotoMetaKeys.DateTaken.


1
Enum case не может содержать повторяющиеся значения. Так что это не подходит для всех сценариев.
— Aaina Jain

@AainaJain На самом деле, если вычисленные свойства используются для значений вместо необработанного значения enum, легко, чтобы разные случаи перечисления выводили одно и то же значение.
— Адам будущего

14

Или просто в GlobalConstants.swift:

import Foundation

let someNotification = "aaaaNotification"

8

Как уже упоминалось, все, что объявлено вне класса, является глобальным.

Вы также можете создавать синглтоны:

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

Всякий раз, когда вы хотите использовать что-то из этого класса, вы, например, пишете:

TestClass.sharedInstance.number = 1

Если вы сейчас напишите println(TestClass.sharedInstance.number)из любого места в вашем проекте, вы напечатаете1 в журнал. Это работает для всех видов объектов.

tl; dr: Каждый раз, когда вы хотите сделать все в классе глобальным, добавить static let sharedInstance = YourClassName()его в класс и обратиться ко всем значениям класса с префиксомYourClassName.sharedInstance


вопрос для вас. другие ответы включают использование struct для хранения информации, но потенциальная проблема заключается в том, что struct является типом значения, class является ссылочным типом, назначение экземпляра класса в struct приведет к грубому переходу класса в тип значения, что нежелательно, верно?
— Martian2049

5

То, что я сделал в своем проекте Swift
1. Создание нового файла Swift
2. Создание в нем структуры и статической константы.
3: Для использования просто используйте YourStructName.baseURL

Примечание. После создания инициализация занимает немного времени, поэтому через 2-5 секунд она будет отображаться в других контроллерах представления.

import Foundation

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

3

Для уведомлений вы можете использовать расширение, что-то вроде этого:

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

И используйте это как NotificationCenter.default.post(name: .testNotification, object: nil)


2

Чтобы иметь глобальные константы в моих приложениях, это то, что я делаю в отдельном файле Swift :

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

Его легко использовать, и звонить везде так:

print(Config.Notifications.awareUser)

1

Цвета

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

шрифты

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

Для других - все так же, как в принятом ответе.


1

Согласно документам swift, глобальные переменные объявляются в области видимости файла.

Глобальные переменные - это переменные, которые определены вне какой-либо функции, метода, замыкания или типа контекста.

Просто создайте быстрый файл (например, Constnats.swift) и объявите там свои константы:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"

и вызывайте его из любой точки вашего проекта, не упоминая имя struct, enum или class.

// MyViewController.swift

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

Я думаю, что это намного лучше для читабельности кода.


1

Версия Swift 4

Если вы хотите создать имя для NotificationCenter:

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

Подписаться на уведомления:

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

Отправить уведомление:

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

Если вы просто хотите использовать класс с переменными:

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

Или:

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

1

Также можно использовать перечисления без регистра.

Преимущество - они не могут быть созданы.

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

0

Учиться у Apple - лучший способ.

Например, уведомление от клавиатуры 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

}

Теперь я учусь у Apple:

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

Более того 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

}

Теперь я изучаю форму 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"

}

использование:

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

Учиться у Apple - это то, что каждый может сделать и легко продвигать качество вашего кода.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.