File konstanta global di Swift


336

Dalam proyek Objective-C saya, saya sering menggunakan file konstanta global untuk menyimpan hal-hal seperti nama dan kunci notifikasi NSUserDefaults. Itu terlihat seperti ini:

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Bagaimana saya melakukan hal yang persis sama di Swift?


3
Anda dapat melihat tutoiral
Anish Parajuli 웃

Jawaban:


765

Structs sebagai namespace

IMO cara terbaik untuk menangani konstanta jenis itu adalah dengan membuat Struct.

struct Constants {
    static let someNotification = "TEST"
}

Lalu, misalnya, panggil seperti ini di kode Anda:

print(Constants.someNotification)

Bersarang

Jika Anda menginginkan organisasi yang lebih baik, saya sarankan Anda menggunakan substruktur yang tersegmentasi

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

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

Maka Anda bisa menggunakan misalnya K.Path.Tmp

Contoh dunia nyata

Ini hanyalah solusi teknis, implementasi aktual dalam kode saya lebih mirip:

struct GraphicColors {

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

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

dan


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
Secara pribadi, saya mencari Constant.swiftfile dengan struct terpisah tetapi tidak dienkapsulasi dalam Constantsstruct besar untuk menghindari panggilan terlalu lama ke sebuah konstanta. Jadi saya menelepon NotificationKey.WelcomebukannyaConstants.NotificationKey.Welcome
Kevin Hirsch

2
@ KirevHirsch bukan ide yang buruk. Di sisi lain: jika saya memiliki awalan .Constants, saya tahu bahwa itu bukan hal lokal, tetapi semacam dalam namespace Constants
brainray

3
@brainray Saya mengerti maksud Anda tetapi dalam kode saya, konstanta tidak pernah lokal (selalu dalam a Constants.swift) dan selalu terlihat sama: dimulai dengan huruf besar dan dengan nama kategori yang bermakna seperti "NotificationKey", "SegueIdentifier" atau "Path", .. Jadi saya bisa melihat dengan mudah ketika itu adalah konstan;)
Kevin Hirsch

15
Ini tidak kompatibel dengan kode Objective-C (struct, atau konstanta tingkat atas diekspor untuk 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

Saya terlambat ke pesta.

Tidak masalah di sini adalah bagaimana saya mengelola file konstanta sehingga lebih masuk akal bagi pengembang saat menulis kode dengan cepat.

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

Untuk CUSTOMFONTS:

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

UNTUK SEMUA KUNCI YANG DIGUNAKAN DALAM APLIKASI

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

UNTUK WARNA KONSTAN:

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

Anda dapat membungkus semua file ini dalam grup umum bernama Konstanta di Proyek Xcode Anda.

Dan untuk lebih banyak tonton video ini


terima kasih, saya menemukan metode Anda menjadi yang paling nyaman (bagi saya setidaknya), bagus sekali! 8)
Yatko

2
lebih baik daripada jawaban saya
Kirit Vaghela

1
Jangan lupa untuk mengimpor UIKit :)
alicanbatur

2
Tidakkah variabel statis meningkatkan ukuran aplikasi selama waktu berjalan karena semua variabel statis dimuat saat aplikasi mulai berjalan?
Anand

1
Saya tahu ini sudah lebih dari setahun, tetapi hanya ingin mengatakan ini fantastis. Dilakukan dengan baik untuk berbagi pengetahuan tentang ini user
user1898712

28

Meskipun saya lebih suka cara @ Francescu (menggunakan struct dengan properti statis), Anda juga dapat mendefinisikan konstanta dan variabel global:

let someNotification = "TEST"

Namun perlu dicatat bahwa secara berbeda dari variabel / konstanta lokal dan properti kelas / struct, globals secara implisit malas, yang berarti mereka diinisialisasi ketika diakses pertama kali.

Bacaan yang disarankan: Variabel Global dan Lokal , dan juga variabel Global di Swift bukan variabel


Ini adalah cara yang tepat untuk mendeklarasikan konstanta. Pendekatan struct sangat baik untuk keterbacaan.
João Nunes

1
Saya tidak merekomendasikan pendekatan ini karena mengosongkan prinsip OOP .. Anda dapat melihat laporan
Anish Parajuli 웃

1
@ThatlazyiOSGuy 웃 Swift adalah bahasa OOP tetapi fokusnya lebih ke pemrograman fungsional juga (setidaknya lebih banyak konsep fungsional). Ini adalah cara yang benar-benar valid untuk mendeklarasikan konstanta meskipun itu akan sangat mengaburkan String namespace untuk setiap IDE.
Dean Kelly

Anda mengatakan perbedaannya adalah dalam kemalasan implisit tetapi jika Anda menggunakan var statis terkomputasi, ia akan bertindak dengan cara yang sama seperti yang dilakukan global dan dikirim sekali dan hanya sekali dipanggil.
Dean Kelly

1
tunggu, tetapi masalah potensial adalah bahwa struct adalah tipe nilai, kelas adalah tipe referensi, menetapkan instance kelas dalam struct akan kelas kasar menjadi tipe nilai, yang tidak diinginkan ??
Martian2049

23

Konstan. Cepat

import Foundation

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

LihatController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

Untuk alasan apa menggunakan kBaseURL dan bukan BASEURL? Terima kasih!
Josep Escobar

Masalahnya dia juga mengembangkan aplikasi android dan ini adalah standar android.
BoranA

5
Ada pola untuk konstanta di Objective-C, Anda akan selalu mendeklarasikannya menggunakan format berikut: k + camel case name of property
Laur Stefan

20

Pertimbangkan enumerasi. Ini dapat dipecah secara logis untuk kasus penggunaan terpisah.

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

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

Satu manfaat unik terjadi ketika Anda memiliki situasi pilihan yang saling eksklusif, seperti:

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

Dalam contoh ini, Anda akan menerima kesalahan kompilasi karena Anda belum menangani kasus ini PhotoMetaKeys.DateTaken.


1
Enum case tidak dapat menyimpan nilai duplikat. Jadi ini tidak akan cocok di semua skenario.
Aaina Jain

@ AainaJain Sebenarnya, jika properti yang dikomputasi digunakan untuk nilai alih-alih nilai mentah enum, mudah untuk membuat case enum yang berbeda menghasilkan nilai yang sama.
future-adam

14

Atau hanya di GlobalConstants.swift:

import Foundation

let someNotification = "aaaaNotification"

8

Seperti yang telah disebutkan orang lain, apa pun yang dinyatakan di luar kelas adalah global.

Anda juga dapat membuat lajang:

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

Setiap kali Anda ingin menggunakan sesuatu dari kelas ini, Anda misalnya menulis:

TestClass.sharedInstance.number = 1

Jika sekarang Anda menulis println(TestClass.sharedInstance.number)dari mana saja di proyek Anda, Anda akan mencetak 1ke log. Ini berfungsi untuk semua jenis objek.

tl; dr: Kapan pun Anda ingin membuat segalanya di kelas global, tambahkan static let sharedInstance = YourClassName()ke kelas, dan alamat semua nilai kelas dengan awalanYourClassName.sharedInstance


sebuah pertanyaan untukmu. jawaban lain melibatkan penggunaan struct untuk menyimpan informasi, tetapi masalah potensial adalah bahwa struct adalah tipe nilai, kelas adalah tipe referensi, menugaskan instance kelas dalam struct akan kelas kasar menjadi tipe nilai, yang tidak diinginkan, kan?
Martian2049

5

Apa yang saya lakukan dalam proyek Swift
1 saya: Buat File Swift baru
2: Buat struct dan konstanta statis di dalamnya.
3: Untuk Menggunakan cukup gunakan YourStructName.baseURL

Catatan: Setelah Membuat inisialisasi dibutuhkan sedikit waktu sehingga akan ditampilkan di viewcontrollers lain setelah 2-5 detik.

import Foundation

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

3

Untuk pemberitahuan Anda dapat menggunakan ekstensi, sesuatu seperti ini:

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

Dan gunakan itu seperti NotificationCenter.default.post(name: .testNotification, object: nil)


2

Untuk memiliki konstanta global di aplikasi saya, inilah yang saya lakukan di file Swift yang terpisah :

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

Mudah digunakan, dan menelepon ke mana-mana seperti ini:

print(Config.Notifications.awareUser)

1

Warna

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

Font

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

Untuk yang lain - semuanya sama dengan jawaban yang diterima.


1

Menurut dokumen global cepat variabel dinyatakan dalam ruang lingkup file.

Variabel global adalah variabel yang didefinisikan di luar fungsi, metode, penutupan, atau konteks tipe apa pun

Cukup buat file cepat (Contoh: Constnats.swift) dan nyatakan konstanta Anda di sana:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"

dan menyebutnya dari mana saja di proyek Anda tanpa perlu menyebutkan struct, enum atau nama kelas.

// MyViewController.swift

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

Saya pikir ini jauh lebih baik untuk pembacaan kode.


1

Versi Swift 4

Jika Anda ingin membuat nama untuk NotificationCenter:

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

Berlangganan pemberitahuan:

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

Kirim pemberitahuan:

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

Jika Anda hanya ingin kelas dengan variabel untuk digunakan:

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

Atau:

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

1

Enum yang tidak bertali juga bisa digunakan.

Keuntungan - Mereka tidak dapat dipakai.

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

0

Belajar dari Apple adalah cara terbaik.

Misalnya, notifikasi keyboard 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

}

Sekarang saya belajar dari Apple:

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

Terlebih lagi 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

}

Sekarang saya belajar dari 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"

}

pemakaian:

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

Belajar dari Apple adalah cara yang dapat dilakukan semua orang dan dapat mempromosikan kualitas kode Anda dengan mudah.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.