119

Simply I have a struct that stores the application constants as below:

struct Constant {

    static let ParseApplicationId = "xxx"
    static let ParseClientKey = "xxx"

    static var AppGreenColor: UIColor {
        return UIColor(hexString: "67B632")
    }
}

These constants can be use in Swift code by calling Constant.ParseClientKey for example. But in my code, it also contains some Objective-C classes. So my question is how to use these constants in the Objective-C code?

If this way to declare constants is not good then what is the best way to create global constants to be used in both Swift and Objective-C code?

6
  • 31
    Please follow common swift code style and use a lowercase letter to start your let/var identifiers. Commented Oct 3, 2014 at 14:37
  • 6
    @NikolaiRuhe Would this not be the correct style for static properties of a struct? Much like UIControlEvents.TouchUpInside? Commented Aug 24, 2015 at 11:38
  • 1
    @NikolaiRuhe Take a look at the Swift declaration: developer.apple.com/library/ios/documentation/UIKit/Reference/… — it's definitely a struct. Commented Aug 25, 2015 at 10:01
  • 1
    @LukeRogers That's because of Swift 2.0's changed way of how to import NS_OPTIONS style enums. Semantically UIControlEvent is still an enumeration type. Commented Aug 25, 2015 at 11:02
  • 11
    @NikolaiRuhe LukeRogers: Dinh didn't ask about that issue, and most of us viewers didn't click here to read about it. Commented Oct 3, 2016 at 21:23

4 Answers 4

135

Sad to say, you can not expose struct, nor global variables to Objective-C. see the documentation, which states in part:

Use Classes When You Need Objective-C Interoperability

If you use an Objective-C API that needs to process your data, or you need to fit your data model into an existing class hierarchy defined in an Objective-C framework, you might need to use classes and class inheritance to model your data. For example, many Objective-C frameworks expose classes that you are expected to subclass.

As of now, IMHO, the best way is something like this:

let ParseApplicationId = "xxx"
let ParseClientKey = "xxx"
let AppGreenColor = UIColor(red: 0.2, green: 0.7, blue: 0.3 alpha: 1.0)

@objc class Constant: NSObject {
    private init() {}

    class func parseApplicationId() -> String { return ParseApplicationId }
    class func parseClientKey() -> String { return ParseClientKey }
    class func appGreenColor() -> UIColor { return AppGreenColor }
}

In Objective-C, you can use them like this:

NSString *appklicationId = [Constant parseApplicationId];
NSString *clientKey = [Constant parseClientKey];
UIColor *greenColor = [Constant appGreenColor];
Sign up to request clarification or add additional context in comments.

8 Comments

Accessible to Swift also?
@khunshan Yes. Accessible directly ParseClientKey, or via the class Constant.clientKey()
Should use @objc class Constant: NSObject
This works but in Swift 4, I also needed to put @objc in front of every class func to be able to call them from Objective C code.
@ElectroBuddha You can do @objcMembers on the class to reveal the whole class to Objective-C code.
|
29

Why not create a file with both a struct and an @objc class, something like this:

import UIKit

extension UIColor {
    convenience init(hex: Int) {
        let components = (
            R: CGFloat((hex >> 16) & 0xff) / 255,
            G: CGFloat((hex >> 08) & 0xff) / 255,
            B: CGFloat((hex >> 00) & 0xff) / 255
        )
        self.init(red: components.R, green: components.G, blue: components.B, alpha: 1)
    }
}

extension CGColor {
    class func colorWithHex(hex: Int) -> CGColorRef {
        return UIColor(hex: hex).CGColor
    }
}

struct Constant {
    static let kParseApplicationId = "5678"
    static let kParseClientKey = "1234"
    static var kAppGreenColor: UIColor { return UIColor(hex:0x67B632) }
    static var kTextBlackColor: UIColor { return UIColor(hex:0x000000) }
    static var kSomeBgBlueColor: UIColor { return UIColor(hex:0x0000FF) }
    static var kLineGrayCGColor: CGColor { return CGColor.colorWithHex(0xCCCCCC) }
    static var kLineRedCGColor: CGColor { return CGColor.colorWithHex(0xFF0000) }
}


@objc class Constants: NSObject {
    private override init() {}

    class func parseApplicationId() -> String { return Constant.kParseApplicationId }
    class func parseClientKey() -> String { return Constant.kParseClientKey }
    class func appGreenColor() -> UIColor { return Constant.kAppGreenColor }
    class func textBlackColor() -> UIColor { return Constant.kTextBlackColor }
    class func someBgBlueColor() -> UIColor { return Constant.kSomeBgBlueColor }
    class func lineGrayCGColor() -> CGColor { return Constant.kLineGrayCGColor }
    class func lineRedCGColor() -> CGColor { return Constant.kLineRedCGColor }
}

For use in Objective-C files add this when you need to use constants:

#import "ProjectModuleName-Swift.h"

Swift usage:

self.view.backgroundColor = Constant.kAppGreenColor

Objective-C usage:

self.view.backgroundColor = [Constants appGreenColor];

This way you can update colors, default text, web service urls for whole app in one place.

1 Comment

It wasn't immediately clear to me that we could scroll your answer to discover the objective-c part!
3

Though this might be late or redundant, I could make it work with the following code :

@objcMembers class Flags: NSObject {
    static let abcEnabled = false
    static let pqrEnabled = false
    .
    .
    .
}

Obviously, to use in objc c code, you have to do #import "ProjectModuleName-Swift.h"

Comments

1

You should make the let statements private if you want to make other Swift types in your code to access these constants only via class:

private let AppGreenColor = UIColor(red: 0.2, green: 0.7, blue: 0.3 alpha: 1.0)

@objc class Constant {
    class func appGreenColor() -> UIColor { return AppGreenColor }
}

In Swift, you can use them like this:

UIColor *greenColor = Constant.appGreenColor

The following line will not compile anymore now since the let statement is private:

UIColor *greenColor = appGreenColor

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.