在我的Objective-C项目中,我经常使用全局常量文件来存储诸如NSUserDefaults的通知名称和键之类的东西。看起来像这样:

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end


我该如何在Swift中做完全相同的事情?

评论

您可以看到本教程

#1 楼

将结构作为名称空间

IMO处理此类常量的最佳方法是创建一个结构。

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


评论


就个人而言,我去了一个带有分离结构的Constant.swift文件,但没有封装在一个大的Constants结构中,以避免对一个常量的调用时间太长。所以我叫NotificationKey.Welcome而不是Constants.NotificationKey.Welcome

–凯文·赫希(Kevin Hirsch)
15年2月24日在10:31

@KevinHirsch不错。另一方面:如果我有.Constants前缀,我知道这不是本地的东西,而是名称空间中的常量。

–brainray
2015年5月7日14:22

@brainray我明白您的意思,但是在我的代码中,常量永远不会是局部常量(始终在Constants.swift中)并且总是一样:以大写字母开头,并使用有意义的类别名称,例如“ NotificationKey”,“ SegueIdentifier”或“ Path” ,...所以当它是常数时,我可以很容易地看到它;)

–凯文·赫希(Kevin Hirsch)
2015年5月7日17:05

这与Objective-C代码没有交叉兼容(结构,也没有为Objective-C导出顶级常量)。

– RndmTsk
2015年11月5日,19:23

@VarunNaharia struct Helpers {静态函数RGBCOLOR(红色:Int,绿色:Int,蓝色:Int)-> UIColor {返回UIColor(红色:CGFloat(红色)/ 255.0,绿色:CGFloat(绿色)/ 255.0,蓝色:CGFloat(蓝色)/ 255.0,alpha:1)}静态函数IOS7VERSION()-> Bool {return UIDevice.currentDevice()。systemVersion.compare(“ 7.0”,选项:.NumericSearch,范围:nil,语言环境:nil)!=。 OrderedAscending}}

–AndréSlotta
15年11月20日在16:56

#2 楼

我迟到了。

无论我是如何管理常量文件的,这样开发人员在快速编写代码时就更有意义。

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


用于自定义字体:

//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项目中名为“常量”的通用组中。 br />
有关更多信息,请观看此视频

评论


谢谢,我发现您的方法最方便(至少对我来说),做得很好! 8)

– Yatko
17年8月8日在1:16

不要忘了导入UIKit :)

– Alicanbatur
17年3月28日在11:17

等待,但是潜在的问题是struct是值类型,class是引用类型,在struct中分配类实例会使class粗化为value类型,这是不希望的?

–Martian2049
17年9月14日在6:16

静态变量不会在运行时增加应用程序的大小,因为当应用程序开始运行时会加载所有静态变量吗?

– Anand
17年12月6日在11:36

我知道这已经一年多了,但是只是想说这太棒了。分享这方面的知识做得好👌🏻

–user1898712
19-09-17在15:43

#3 楼

尽管我更喜欢@Francescu的方式(使用具有静态属性的结构),但是您也可以定义全局常量和变量:

let someNotification = "TEST"


但是请注意,它不同于局部变量/常量和类/结构属性,全局变量是隐式惰性的,这意味着它们在首次访问时会被初始化。

建议阅读:全局和局部变量,以及Swift中的全局变量都不是变量

评论


这是声明常量的正确方法。 struct方法对于可读性非常好。

–JoãoNunes
16年2月16日在10:24

我不建议您使用这种方法,因为它会使OOP原则无效。

–阿尼(Anish Parajuli)웃
17-2-26在1:56



@ThatlazyiOSGuy웃Swift是一种OOP语言,但重点也更多地放在函数编程上(至少是更多的函数概念)。尽管这会严重混淆任何IDE的String名称空间,但这是声明常量的一种完全有效的方法。

–迪恩·凯利
17年5月25日在21:22

您说的区别在于隐式懒惰,但是如果您使用计算的静态var,它将以与global相同的方式起作用,并且仅一次调用一次。

–迪恩·凯利
17年5月25日在21:24

等待,但是潜在的问题是struct是值类型,class是引用类型,在struct中分配类实例会使class粗化为value类型,这是不希望的?

–Martian2049
17年9月14日在6:16

#4 楼

Constant.swift

import Foundation

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


ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)


评论


由于什么原因使用kBaseURL而不是BASEURL?谢谢!

–约瑟夫·埃斯科巴尔
16-10-16在17:15

大概他也正在开发android应用程序,这是android的标准。

– BoranA
16年1月1日在8:04

在Objective-C中有一个常量模式,您将始终使用以下格式声明它们:k + camel属性的大小写名称

–Laur Stefan
17 Mar 24 '17在15:36

#5 楼

考虑枚举。这些可以在逻辑上针对不同的用例进行分解。

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的情况。

评论


枚举大小写不能包含重复值。因此,这并不适合所有情况。

– Aaina Jain
18-3-8的4:02



@AainaJain实际上,如果将计算属性用作值而不是枚举原始值,则很容易让不同的枚举案例输出相同的值。

–adamjansch
19年1月3日,17:06

#6 楼

或者只是在GlobalConstants.swift中:

import Foundation

let someNotification = "aaaaNotification"


#7 楼

就像其他人提到的那样,在类外声明的任何内容都是全局的。

还可以创建单例:

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


无论何时您想使用某些东西从这个班上,你例如写入:

TestClass.sharedInstance.number = 1


如果现在从项目中的任何位置写入println(TestClass.sharedInstance.number),则将1打印到日志中。这适用于所有类型的对象。

dr:任何时候,只要您想使一个类中的所有内容都变为全局性,请将static let sharedInstance = YourClassName()添加到该类中,并使用前缀YourClassName.sharedInstance <对该类的所有值进行寻址

评论


给你一个问题。其他答案涉及使用struct来存储信息,但是潜在的问题是struct是值类型,class是引用类型,在struct中分配类实例会将class粗化为value类型,这是不希望的,对吧?

–Martian2049
17年9月14日在6:18

#8 楼

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


#9 楼

要在我的应用程序中包含全局常量,这是我在单独的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)


#10 楼

对于通知,您可以使用扩展名,例如:

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


并像NotificationCenter.default.post(name: .testNotification, object: nil)
一样使用它

#11 楼

也可以使用无大小写的枚举。

优点-无法实例化。

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


#12 楼

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


#13 楼

颜色

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


对于其他-一切与接受的答案相同。

#14 楼

根据swift docs,全局变量在文件范围内声明。


全局变量是在任何函数,方法,闭包或类型上下文之外定义的变量


只需创建一个swift文件(例如:Constnats.swift)并在其中声明常量即可:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"


,可以在项目中的任何位置调用它而无需需要提及struct,enum或类名。

// MyViewController.swift

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


我认为这对于代码可读性而言要好得多。

#15 楼

向苹果学习是最好的方法。例如,苹果的键盘通知:

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

}


现在我向苹果学习:

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

}


现在我从苹果学习形式:

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学习是每个人都可以做的方法,并且可以提高代码质量轻松。

评论


如何在完全不同的类中访问自己的常量?

–布赖恩·莱因霍尔德(Brian Reinhold)
20年9月2日在21:55