Swift'te global sabitler dosyası


336

Objective-C projelerimde genellikle bildirim adları ve anahtarları gibi şeyleri saklamak için genel sabitler dosyası kullanırım NSUserDefaults. Şuna benziyor:

@interface GlobalConstants : NSObject

extern NSString *someNotification;

@end

@implementation GlobalConstants

NSString *someNotification = @"aaaaNotification";

@end

Aynı şeyi Swift'te nasıl yaparım?


Yanıtlar:


765

Ad alanı olarak yapılar

IMO, bu tür sabitlerle başa çıkmanın en iyi yolu bir Yapı oluşturmaktır.

struct Constants {
    static let someNotification = "TEST"
}

Ardından, örneğin, kodunuzda şu şekilde arayın:

print(Constants.someNotification)

yuvalama

Daha iyi bir organizasyon istiyorsanız, bölümlere ayrılmış alt yapıları kullanmanızı öneririm

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

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

Sonra sadece örneğin K.Path.Tmp

Gerçek dünya örneği

Bu sadece teknik bir çözüm, kodumdaki gerçek uygulama daha çok benziyor:

struct GraphicColors {

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

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

ve


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
Şahsen, Constant.swiftayrı yapılara sahip bir dosyaya gittim, ancak büyük birConstants bir sabite çok uzun çağrı yapılmasını önlemek yapıda . Ben de NotificationKey.Welcomebunun yerine arıyorumConstants.NotificationKey.Welcome
Kevin Hirsch

2
@KevinHirsch kötü bir fikir değil. Öte yandan: .Constants önekine sahipsem, bunun yerel bir şey olmadığını, ancak Constant ad adında bir tür olduğunu biliyorum.
brainray

3
@brainray Ben senin noktasını görüyorum ama benim kodunda, sabitleri asla yerel (her zaman a Constants.swift) ve her zaman aynı görünüyor: büyük harf ile başlayan ve "NotificationKey", "SegueIdentifier" veya "Path" gibi anlamlı bir kategori adıyla .. Bu yüzden sabit olduğunda kolayca görebiliyorum;)
Kevin Hirsch

15
Bu, Objective-C kodu ile çapraz uyumlu değildir (Objective-C için yapılar veya üst düzey sabitler dışa aktarılmaz).
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

Partiye çok geç kaldım.

Olursa olsun nasıl hızlı bir şekilde kod yazarken geliştiriciler için daha mantıklı böylece sabitleri dosyayı yönetmek nasıl.

URL İÇİN:

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

ÖZEL FONLAR için:

//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 KULLANILAN TÜM ANAHTARLAR İÇİN

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

RENK SABİTLERİ İÇİN:

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

Bu tüm dosyaları Xcode Projenizdeki Sabitler adlı ortak bir gruba sarabilirsiniz .

Ve daha fazlası için bu videoyu izleyin


teşekkürler, yönteminizi en uygun buldum (en azından benim için), aferin! 8)
Yatko


1
UIKit ithal etmeyi unutmayın :)
alicanbatur

2
Statik değişkenler, uygulama çalışmaya başladığında tüm statik değişkenler yüklendiği için çalışma sırasında uygulamanın boyutunu artırmıyor mu?
Anand

1
Bu bir yıldan eski olduğunu biliyorum, ama sadece bu harika olduğunu söylemek istedim. Bu 👌🏻 hakkında bilgi paylaşmak için aferin
user1898712

28

@ Francescu'nun yolunu (statik özelliklere sahip bir yapı kullanarak) tercih etsem de, global sabitleri ve değişkenleri de tanımlayabilirsiniz:

let someNotification = "TEST"

Bununla birlikte, yerel değişkenlerin / sabitlerin ve sınıf / yapı özelliklerinden farklı olarak, globallerin örtülü olarak tembel olduğunu, yani ilk kez erişildiklerinde başlatıldıkları anlamına gelir.

Önerilen okuma: Global ve Yerel Değişkenler ve ayrıca Swift'teki Global değişkenler değişken değildir


Bu sabitleri bildirmenin doğru yoludur. Yapı yaklaşımı okunabilirlik için çok iyidir.
João Nunes

1
OOP prensibini geçersiz kıldığı için
önermiyorum ..

1
@ThatlazyiOSGuy 웃 Swift bir OOP dilidir ancak odak noktası daha çok işlevsel programlamaya yöneliktir (en azından daha fazla fonksiyonel kavram). Bu, herhangi bir IDE için String ad alanını ciddi bir şekilde bulutlayacak olsa da, sabitleri bildirmenin mükemmel bir yoludur.
Dean Kelly

Farkın örtülü tembellik içinde olduğunu söylersiniz, ancak hesaplanmış statik bir var kullanırsanız, bir global gibi davranacak ve bir kez ve sadece bir kez gönderilecektir.
Dean Kelly

1
bekleyin, ancak potansiyel sorun, yapı değer türü, sınıfın başvuru türü olmasıdır, yapı içinde sınıf örneği atamak, sınıfı istenmeyen değer türüne kaba gönderir?
Martian2049

23

Constant.swift

import Foundation

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

ViewController.swift

var manager = AFHTTPRequestOperationManager(baseURL: kBaseURL)

Hangi nedenle BASEURL yerine kBaseURL kullanır? Teşekkürler!
Josep Escobar

Muhtemelen aynı zamanda android uygulamaları geliştiriyor ve bir android standardı.
BoranA

5
Objective-C'de sabitler için bir desen vardır, bunları her zaman bir sonraki formatı kullanarak ilan edersiniz: k + mülkiyetin mülkiyet adı
Laur Stefan

20

Numaralandırmayı düşünün. Bunlar ayrı kullanım durumları için mantıksal olarak ayrılabilir.

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

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

Benzersiz bir avantaj, karşılıklı olarak münhasır seçeneklerin bulunduğu bir durum olduğunda ortaya çıkar, örneğin:

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

Bu örnekte, vakasını işlemediğiniz için bir derleme hatası alacaksınız PhotoMetaKeys.DateTaken.


1
Numaralandırma durumu yinelenen değerleri tutamaz. Yani bu tüm senaryolara uymayacak.
Aaina Jain

@AainaJain Aslında, hesaplanmış özellikler enum raw değeri yerine değerler için kullanılırsa, farklı enum kasalarının aynı değeri vermesi kolaydır.
future-adam

14

Veya yalnızca GlobalConstants.swift içinde:

import Foundation

let someNotification = "aaaaNotification"

8

Diğerlerinin de belirttiği gibi, sınıf dışında beyan edilen her şey küreseldir.

Ayrıca tektonlar da oluşturabilirsiniz:

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

Bu sınıftan bir şey kullanmak istediğinizde, örneğin şunları yazabilirsiniz:

TestClass.sharedInstance.number = 1

Şimdi println(TestClass.sharedInstance.number)projenizin herhangi bir yerinden yazıyorsanız,1 günlüğe . Bu, her türlü nesne için geçerlidir.

tl; dr: Bir sınıftaki her şeyi global yapmak istediğinizde, sınıfa ekleyin static let sharedInstance = YourClassName()ve sınıfın tüm değerlerini önekle ele alınYourClassName.sharedInstance


senin için bir soru. diğer cevaplar bilgiyi saklamak için yapıyı kullanmayı içerir, ancak potansiyel sorun, yapının değer türü, sınıfın referans türü olması, yapıda sınıf örneği atamak, sınıfı istenmeyen değer türüne kaba gönderir, öyle değil mi?
Martian2049

5

Swift projemde ne yaptım
1: Yeni Swift Dosyası
Oluştur 2: İçinde bir yapı ve statik sabit oluşturun.
3: Kullanmak için YourStructName.baseURL kullanın

Not: Oluşturma işleminden sonra başlatma işlemi çok az zaman alır, bu nedenle 2-5 saniye sonra diğer görünüm denetleyicilerinde gösterilir.

import Foundation

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

3

Bildirimler için uzantıyı kullanabilirsiniz, şuna benzer:

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

Ve şu şekilde kullanın NotificationCenter.default.post(name: .testNotification, object: nil)


2

Uygulamalarımda global sabitlere sahip olmak için ayrı bir Swift dosyasında yaptığım şey :

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

Kullanımı ve böyle her yeri aramak kolaydır:

print(Config.Notifications.awareUser)

1

Renkler

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

Yazı

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

Diğerleri için - her şey kabul edilen cevaptakiyle aynıdır.


1

Göre hızlı docs küresel değişkenler dosya kapsamı bildirilmiştir.

Genel değişkenler, herhangi bir işlev, yöntem, kapatma veya tür bağlamının dışında tanımlanan değişkenlerdir

Sadece hızlı bir dosya oluşturun (Örn: Constnats.swift) ve sabitlerinizi orada beyan edin:

// Constants.swift

let SOME_NOTIF = "aaaaNotification"

yapı, numaralandırma veya sınıf adından bahsetmeden projenizin herhangi bir yerinden arayabilirsiniz.

// MyViewController.swift

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

Bu kod okunabilirliği için çok daha iyi olduğunu düşünüyorum.


1

Swift 4 Sürümü

NotificationCenter için bir ad oluşturmak istiyorsanız:

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

Bildirimlere abone olun:

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

Bildirim gönder:

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

Yalnızca değişkenleri olan bir sınıfın kullanılmasını istiyorsanız:

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

Veya:

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

1

Dikkatsiz numaralandırmalar da kullanılabilir.

Avantaj - Örneklenemezler.

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

0

Apple'dan öğrenmek en iyi yoldur.

Örneğin, Apple'ın klavye bildirimi:

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

}

Şimdi Apple'dan öğreniyorum:

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

Ne, daha bulunuyor 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

}

Şimdi Apple formunu öğreniyorum:

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"

}

kullanımı:

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

Apple'dan öğrenin, herkesin yapabileceği yöntemdir ve kod kalitenizi kolayca yükseltebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.