Файл глобальних констант у Swift


336

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

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Як мені зробити те саме, що у Swift?


3
Ви можете ознайомитись із цим тутайралом
Аніш Параджулі

Відповіді:


765

Структури як простір імен

Найкращим способом боротьби з таким типом констант є ІМО - створення Структури.

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, я знаю, що це не місцева річ, а вид константи простору імен
brainray

3
@brainray Я бачу вашу думку, але в моєму коді константи ніколи не є локальними (завжди в а 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 } }
André

109

Я спізнююсь до партії.

Незалежно від того, як я керую файлом констант, щоб було більше сенсу розробникам, коли швидко писати код.

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

ДЛЯ ВСІХ КЛЮЧІВ, ВИКОРИСТАНИХ В 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"
        }
    }

ДЛЯ КОНСТАНТІВ КОЛЬОРУ:

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

Ви можете об'єднати ці всі файли у загальну групу з назвою Константи у своєму проекті Xcode.

А для більшого перегляду цього відео


дякую, я знайшов ваш метод найзручнішим (принаймні для мене), молодцем! 8)
Ятько

2
краще, ніж моя відповідь
Кіріт Вагела

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

2
Чи статичні змінні не збільшують розмір програми під час виконання, оскільки всі статичні змінні завантажуються, коли програма починає працювати?
Ананд

1
Я знаю, що це вже більше року, але просто хотів сказати, що це фантастично. Молодці для обміну знаннями з цього 👌🏻
користувача1898712,

28

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

let someNotification = "TEST"

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

Пропоноване читання: глобальні та локальні змінні , а також глобальні змінні в Swift не є змінними


Це правильний спосіб декларування констант. Структурний підхід дуже хороший для читабельності.
Жоао Нунес

1
Я не рекомендую такий підхід, оскільки він анулює
принцип OOP..Ви

1
@ThatlazyiOSGuy i Swift є мовою OOP, але акцент також спрямований на функціональне програмування (принаймні більше функціональних понять). Це ідеально правильний спосіб оголошення констант, хоча він сильно затуманить простір імен String для будь-якого IDE.
Дін Келлі

Ви кажете, що різниця полягає в неявній ліні, але якщо ви використовуєте обчислений статичний var, він буде діяти так само, як робить глобальний, і відправляє один раз і лише один раз викликаний.
Дін Келлі

1
зачекайте, але потенційна проблема полягає в тому, що struct є типовим типом, клас - референсним типом, присвоєння екземпляра класу в struct буде грубим класом у тип значення, який небажаний ??
Martian2049

23

Постійний

import Foundation

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

ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

З якої причини використовується kBaseURL замість BASEURL? Дякую!
Йозеп Ескобар

Проблем, він також розробляє програми для Android, і це андроїд.
BoranA

5
В «Об’єкт-С» є шаблон констант, ви завжди оголошуватимете їх у наступному форматі: 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 Насправді, якщо для значень використовуються обчислювані властивості замість значення перерахунку перерахунків, то у різних випадках перерахунків легко виводити одне і те ж значення.
майбутній-адам

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


питання до вас. Інші відповіді передбачають використання структури для зберігання інформації, але потенційна проблема полягає в тому, що структура - тип значення, клас - тип посилання, присвоєння екземпляру класу в структурі буде грубим класом у тип значення, який є небажаним, правда?
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

Згідно з швидкими документами глобальні змінні оголошуються в області файлів.

Глобальні змінні - це змінні, які визначаються поза будь-яким контекстом функції, методу, закриття чи типу

Просто створіть швидкий файл (наприклад: Constnats.swift) і оголосіть там свої константи:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"

і зателефонуйте йому з будь-якого місця у вашому проекті, не потрібно згадувати ім’я структура, enum чи клас

// 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.