Swiftのグローバル定数ファイル


336

Objective-Cプロジェクトでは、通知用の名前やのキーなどを保存するために、グローバル定数ファイルをよく使用しますNSUserDefaults。次のようになります。

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Swiftでまったく同じことをするにはどうすればよいですか?


回答:


764

名前空間としての構造体

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

123
個人的には、定数への長時間の呼び出しを避けるためConstant.swiftに、構造体が分離されているが大きなConstants構造体にカプセル化されていないファイルを探しました。NotificationKey.Welcome代わりに私は代わりに電話しますConstants.NotificationKey.Welcome
ケビン・ヒルシュ

2
@KevinHirschは悪い考えではありません。一方、.Constantsプレフィックスがある場合、それはローカルのものではなく、名前空間の定数のようなものであることを知っています
May7

3
@brainrayあなたのポイントはわかりますが、私のコードでは、定数は決してローカルではなく(常にConstants.swift)であり、常に同じように見えます。 。だから、それが定数のときは簡単にわかります;)
Kevin Hirsch

15
これは、Objective-Cコードとの互換性がありません(構造体もトップレベルの定数もObjective-Cにエクスポートされます)。
RndmTsk 2015年

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 } }
アンドレ・Slotta

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

アプリで使用されるすべてのキーについて

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

2
私の答えより良い
キリットヴァゲラ2017年

1
UIKitをインポートすることを忘れないでください:)
alicanbatur 2017年

2
静的変数は、アプリの実行開始時にすべての静的変数が読み込まれるため、実行時にアプリのサイズを増やしませんか?
アナンド2017

1
私はこれが1年以上前であることを知っていますが、これは素晴らしいと言いたかっただけです。さて、この👌🏻で知識を共有するためになさ
user1898712

28

私は@Francescuの方法(静的プロパティを持つ構造体を使用)を好みますが、グローバル定数と変数を定義することもできます。

let someNotification = "TEST"

ただし、ローカル変数/定数やクラス/構造体のプロパティとは異なり、グローバルは暗黙的にレイジーです。つまり、最初にアクセスされたときに初期化されます。

推奨される読み物:グローバル変数とローカル変数、およびSwiftのグローバル変数変数ではありません


これは定数を宣言する正しい方法です。構造体のアプローチは、読みやすさのために非常に優れています。
ジョアン・ヌネス

1
OOPの原則が無効になるため、このアプローチはお勧めし
ません。

1
@ThatlazyiOSGuy웃SwiftはOOP言語ですが、焦点は関数型プログラミングにも集中しています(少なくとも関数型の概念)。これは、定数を宣言するための完全に有効な方法ですが、任意のIDEのString名前空間を厳しく曇らせます。
ディーン・ケリー

違いは暗黙の遅延にあると言いますが、計算された静的変数を使用する場合、グローバルと同じように動作し、呼び出されたのは1回だけです。
ディーン・ケリー

1
待機しますが、潜在的な問題は、構造体が値型、クラスが参照型であり、構造体にクラスインスタンスを割り当てると、粗いクラスが値型になり、望ましくないですか?
Martian2049 2017

23

Constant.swift

import Foundation

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

ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

BASEURLの代わりにkBaseURLを使用する理由は何ですか?ありがとう!
Josep Escobar

Problalyはまた、Androidアプリケーションの開発も行っており、それはAndroid標準です。
BoranA 16

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

次のような相互に排他的なオプションの状況がある場合、1つのユニークな利点があります。

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
列挙型のケースでは重複する値を保持できません。したがって、これはすべてのシナリオに適合するわけではありません。
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 2017

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"

そして、構造体、列挙型、クラス名を言及する必要なく、プロジェクトのどこからでもそれを呼び出すことができます。

// 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のキーボード通知:

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から学ぶことは、誰でもできる方法であり、簡単にコードの品質を向上させることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.