Tệp hằng số toàn cầu trong Swift


336

Trong các dự án Objective-C của tôi, tôi thường sử dụng tệp hằng số toàn cầu để lưu trữ những thứ như tên thông báo và khóa cho NSUserDefaults. Nó trông giống như thế này:

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Làm cách nào để thực hiện chính xác điều tương tự trong Swift?


3
Bạn có thể thấy tutoirus
Anish Parajuli

Câu trả lời:


764

Cấu trúc như không gian tên

IMO cách tốt nhất để đối phó với loại hằng số đó là tạo ra Struct.

struct Constants {
    static let someNotification = "TEST"
}

Sau đó, ví dụ, gọi nó như thế này trong mã của bạn:

print(Constants.someNotification)

Làm tổ

Nếu bạn muốn tổ chức tốt hơn, tôi khuyên bạn nên sử dụng các cấu trúc con được phân đoạn

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

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

Sau đó, bạn chỉ có thể sử dụng ví dụ K.Path.Tmp

Ví dụ thế giới thực

Đây chỉ là một giải pháp kỹ thuật, việc triển khai thực tế trong mã của tôi trông giống như:

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
Cá nhân, tôi đã tìm một Constant.swifttập tin với các cấu trúc riêng biệt nhưng không được gói gọn trong một Constantscấu trúc lớn để tránh cuộc gọi quá dài đến một hằng số. Vì vậy, tôi gọi NotificationKey.Welcomethay vìConstants.NotificationKey.Welcome
Kevin Hirsch

2
@KevinHirsch không phải là ý kiến ​​tồi. Mặt khác: nếu tôi có tiền tố .Constants, tôi biết rằng đó không phải là một thứ cục bộ, mà là loại trong không gian tên Hằng số
brainray

3
@brainray Tôi thấy quan điểm của bạn nhưng trong mã của tôi, các hằng số không bao giờ cục bộ (luôn ở dạng a Constants.swift) và luôn trông giống nhau: bắt đầu bằng chữ hoa và với một tên danh mục có ý nghĩa như "NotificationKey", "SegueIdentifier" hoặc "Path", .. . Vì vậy, tôi có thể dễ dàng nhìn thấy khi nó là một hằng số;)
Kevin Hirsch

15
Điều này không tương thích chéo với mã Objective-C (cấu trúc, cũng không phải là hằng số cấp cao nhất được xuất cho 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

Tôi đến bữa tiệc muộn.

Bất kể đây là cách tôi quản lý tệp hằng để nó có ý nghĩa hơn đối với các nhà phát triển trong khi viết mã nhanh chóng.

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

Dành cho khách hàng:

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

CHO TẤT CẢ CÁC PHÍM SỬ DỤNG TRONG ỨNG DỤNG

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

CHO CONSTANTS MÀU:

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

Bạn có thể gói tất cả các tệp này trong một nhóm chung có tên Hằng trong Dự án Xcode của bạn.

Và để biết thêm xem video này


cảm ơn, tôi thấy phương pháp của bạn là thuận tiện nhất (ít nhất là đối với tôi), được thực hiện tốt! 8)
Yatko

2
tốt hơn câu trả lời của tôi
Kirit Vaghela

1
Đừng quên nhập UIKit :)
alicanbatur

2
Các biến tĩnh không làm tăng kích thước của ứng dụng trong thời gian chạy vì tất cả các biến tĩnh được tải khi ứng dụng bắt đầu chạy?
Anand

1
Tôi biết điều này đã hơn một năm tuổi, nhưng chỉ muốn nói điều này thật tuyệt vời. Hoàn thành tốt việc chia sẻ kiến ​​thức về điều này user
user1898712

28

Mặc dù tôi thích cách của @ Francescu (sử dụng cấu trúc có thuộc tính tĩnh), bạn cũng có thể xác định các hằng và biến toàn cục:

let someNotification = "TEST"

Tuy nhiên, lưu ý rằng khác với các biến / hằng cục bộ và các thuộc tính lớp / cấu trúc, toàn cầu hoàn toàn lười biếng, có nghĩa là chúng được khởi tạo khi chúng được truy cập lần đầu tiên.

Đọc gợi ý: Biến toàn cục và biến cục bộ , và cả biến toàn cục trong Swift không phải là biến


Đây là cách chính xác để khai báo các hằng số. Cách tiếp cận struct rất tốt cho khả năng đọc.
João Nunes

1
Tôi không đề xuất cách tiếp cận này vì nó nói lên nguyên tắc OOP..Bạn
Anish Parajuli

1
@ThatlazyiOSGuy 웃 Swift là một ngôn ngữ OOP nhưng trọng tâm cũng tập trung vào lập trình chức năng (ít nhất là nhiều khái niệm chức năng hơn). Đây là một cách hoàn toàn hợp lệ để khai báo các hằng mặc dù nó sẽ che khuất không gian tên String cho bất kỳ IDE nào.
Dean Kelly

Bạn nói rằng sự khác biệt nằm ở sự lười biếng ngầm định nhưng nếu bạn sử dụng var tĩnh được tính toán, nó sẽ hoạt động giống như cách toàn cầu thực hiện và gửi đi một lần và chỉ một lần được gọi.
Dean Kelly

1
chờ đã, nhưng vấn đề tiềm ẩn là struct là kiểu giá trị, lớp là kiểu tham chiếu, gán thể hiện lớp trong struct sẽ lớp thô thành kiểu giá trị, điều này không mong muốn ??
Martian2049

23

Không đổi

import Foundation

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

ViewControll.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

Vì lý do gì sử dụng kBaseURL thay vì BASEURL? Cảm ơn!
Josep Escobar

Problaly anh ấy cũng đang phát triển các ứng dụng Android và đó là một ứng dụng Android nổi bật.
BoranA

5
Có một mẫu cho các hằng số trong Objective-C, bạn sẽ luôn khai báo chúng bằng định dạng tiếp theo: k + tên trường hợp lạc đà của tài sản
Laur Stefan

20

Hãy xem xét liệt kê. Đây có thể được chia nhỏ hợp lý cho các trường hợp sử dụng riêng biệt.

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

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

Một lợi ích duy nhất xảy ra khi bạn có tình huống lựa chọn loại trừ lẫn nhau, chẳng hạn như:

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

Trong ví dụ này, bạn sẽ nhận được một lỗi biên dịch vì bạn chưa xử lý trường hợp PhotoMetaKeys.DateTaken.


1
Trường hợp Enum không thể giữ các giá trị trùng lặp. Vì vậy, điều này sẽ không phù hợp trong tất cả các kịch bản.
Aaina Jain

@AainaJain Trên thực tế, nếu các thuộc tính được sử dụng cho các giá trị thay vì giá trị thô enum, thật dễ dàng để các trường hợp enum khác nhau xuất ra cùng một giá trị.
adam tương lai

14

Hoặc chỉ trong GlobalConstants.swift:

import Foundation

let someNotification = "aaaaNotification"

8

Giống như những người khác đã đề cập, bất cứ điều gì được tuyên bố bên ngoài một lớp là toàn cầu.

Bạn cũng có thể tạo singletons:

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

Bất cứ khi nào bạn muốn sử dụng một cái gì đó từ lớp này, bạn hãy viết:

TestClass.sharedInstance.number = 1

Nếu bây giờ bạn viết println(TestClass.sharedInstance.number)từ bất cứ nơi nào trong dự án của bạn, bạn sẽ in 1vào nhật ký. Điều này làm việc cho tất cả các loại đối tượng.

tl; dr: Bất cứ khi nào bạn muốn làm mọi thứ trong một lớp toàn cầu, hãy thêm static let sharedInstance = YourClassName()vào lớp và giải quyết tất cả các giá trị của lớp bằng tiền tốYourClassName.sharedInstance


Đây là câu hỏi cho bạn. Các câu trả lời khác liên quan đến việc sử dụng struct để lưu trữ thông tin, nhưng vấn đề tiềm ẩn là struct là loại giá trị, lớp là loại tham chiếu, gán thể hiện lớp trong struct sẽ lớp thô thành loại giá trị, không mong muốn, phải không?
Martian2049

5

Những gì tôi đã làm trong dự án Swift
1 của mình: Tạo tệp Swift mới
2: Tạo một cấu trúc và hằng số tĩnh trong đó.
3: Để sử dụng, chỉ cần sử dụng YourSturationName.baseURL

Lưu ý: Sau khi tạo khởi tạo mất ít thời gian nên nó sẽ hiển thị trong các trình điều khiển chế độ xem khác sau 2-5 giây.

import Foundation

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

3

Đối với thông báo bạn có thể sử dụng tiện ích mở rộng, đại loại như thế này:

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

Và sử dụng nó như NotificationCenter.default.post(name: .testNotification, object: nil)


2

Để có các hằng số toàn cầu trong các ứng dụng của tôi, đây là những gì tôi làm trong một tệp Swift riêng :

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

Thật dễ dàng để sử dụng và gọi mọi nơi như thế này:

print(Config.Notifications.awareUser)

1

Màu sắc

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

Phông chữ

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

Đối với người khác - mọi thứ giống như trong câu trả lời được chấp nhận.


1

Theo các tài liệu toàn cầu, các biến toàn cục được khai báo trong phạm vi tệp.

Biến toàn cục là các biến được xác định bên ngoài bất kỳ chức năng, phương thức, bao đóng hoặc bối cảnh loại nào

Chỉ cần tạo một tệp nhanh chóng (Ví dụ: Constnats.swift) và khai báo các hằng số của bạn ở đó:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"

và gọi nó từ bất cứ nơi nào trong dự án của bạn mà không cần phải đề cập đến tên struct, enum hoặc class.

// MyViewController.swift

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

Tôi nghĩ rằng điều này là tốt hơn nhiều cho khả năng đọc mã.


1

Phiên bản Swift 4

Nếu bạn muốn tạo một tên cho NotificationCenter:

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

Theo dõi thông báo:

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

Gửi thông báo:

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

Nếu bạn chỉ muốn một lớp có các biến để sử dụng:

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

Hoặc là:

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

1

Enum Casless cũng có thể được sử dụng.

Ưu điểm - Chúng không thể được khởi tạo.

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

0

Học từ Apple là cách tốt nhất.

Ví dụ: thông báo bàn phím của 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

}

Bây giờ tôi học được từ Apple:

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

Hơn nữa , 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

}

Bây giờ tôi học mẫu 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"

}

sử dụng:

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

Học từ Apple là cách mọi người có thể làm và có thể quảng bá chất lượng mã của bạn một cách dễ dàng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.