Swift의 전역 상수 파일


336

내 Objective-C 프로젝트에서 종종 전역 상수 파일을 사용하여에 대한 알림 이름 및 키와 같은 것을 저장합니다 NSUserDefaults. 다음과 같이 보입니다 :

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Swift에서 정확히 똑같은 일을 어떻게합니까?


답변:


765

네임 스페이스로서의 구조

IMO는 이러한 유형의 상수를 처리하는 가장 좋은 방법은 Struct를 만드는 것입니다.

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
Kevin Hirsch 10

2
@KevinHirsch는 나쁜 생각이 아닙니다. 반면에 .Constants 접두사가있는 경우 로컬이 아니라 네임 스페이스 Constants
brainray

3
@brainray 요점을 알지만 코드에서 상수는 항상 로컬 (항상 a Constants.swift)이며 항상 동일하게 보입니다. 대문자로 시작하고 "NotificationKey", "SegueIdentifier"또는 "Path"와 같은 의미있는 범주 이름으로 시작합니다. 그래서 상수 일 때 쉽게 볼 수 있습니다;)
Kevin Hirsch

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

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 프로젝트에서 Constants 라는 공통 그룹으로 래핑 할 수 있습니다 .

비디오 를 더 보려면


감사합니다. 귀하의 방법이 가장 편리합니다 (적어도 나를 위해). 8)
Yatko

2
내 대답보다 낫다
Kirit Vaghela

1
UIKit 가져 오기를 잊지 마세요 :)
alicanbatur

2
앱 실행이 시작될 때 모든 정적 변수가로드되므로 정적 변수가 런타임 동안 앱의 크기를 늘리지 않습니까?
Anand

1
나는 이것이 1 세 이상이라는 것을 알고 있지만 이것이 환상적이라고 말하고 싶었습니다. 그럼이 👌🏻에 지식을 공유하기 위해 수행
user1898712

28

@Francescu의 방식을 선호하지만 (정적 속성이있는 구조체 사용) 전역 상수와 변수를 정의 할 수도 있습니다.

let someNotification = "TEST"

그러나 지역 변수 / 상수 및 클래스 / 구조체 속성과 달리 전역 변수는 암시 적으로 게 으르므로 처음 액세스 할 때 초기화됩니다.

제안 읽기 : 전역 및 지역 변수Swift의 전역 변수는 변수가 아닙니다.


이것이 상수를 선언하는 올바른 방법입니다. 구조체 접근 방식은 가독성에 매우 좋습니다.
João Nunes

1
이 OOP principle..You이 볼 수 무효화 나는이 방법을 추천 해달라고 tutoiral
아니시 Parajuli 웃

1
@ThatlazyiOSGuy 웃 스위프트는 OOP 언어이지만 기능 프로그래밍 (적어도 더 많은 기능 개념)에 중점을두고 있습니다. 이것은 IDE를 위해 String 네임 스페이스를 심각하게 흐리게하지만 상수를 선언하는 완전히 유효한 방법입니다.
딘 켈리

차이점은 암시 적 게으름에 있다고 말하지만 계산 된 정적 var를 사용하면 전역과 동일한 방식으로 작동하고 한 번만 호출됩니다.
딘 켈리

1
잠깐 그러나 잠재적 인 문제는 struct가 값 유형이고 클래스가 참조 유형이라는 것입니다.
Martian2049

23

Constant.swift

import Foundation

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

ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

어떤 이유로 BASEURL 대신 kBaseURL을 사용합니까? 감사!
Josep Escobar

아마 그는 또한 안드로이드 응용 프로그램을 개발하고 있으며 안드로이드 표준입니다.
BoranA

5
Objective-C에는 상수에 대한 패턴이 있으며 항상 다음 형식을 사용하여 선언합니다. k + camel 부동산 이름
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
열거 형 대소 문자는 중복 값을 보유 할 수 없습니다. 따라서 모든 시나리오에 적합하지는 않습니다.
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 에서 수행 한 작업 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"

struct, enum 또는 class name을 언급 할 필요없이 프로젝트의 어느 곳에서나 호출하십시오.

// MyViewController.swift

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

코드 가독성이 훨씬 낫다고 생각합니다.


1

스위프트 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로부터 배우는 것은 모든 사람이 할 수있는 방법이며 코드 품질을 쉽게 홍보 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.