How to use Swift struct in Objective-C

Objective CSwiftConstants

Objective C Problem Overview


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?

Objective C Solutions


Solution 1 - Objective C

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];

Solution 2 - Objective C

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.

Solution 3 - Objective C

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"

Solution 4 - Objective C

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDinh QuanView Question on Stackoverflow
Solution 1 - Objective CrintaroView Answer on Stackoverflow
Solution 2 - Objective CMarijan V.View Answer on Stackoverflow
Solution 3 - Objective CAnil ArigelaView Answer on Stackoverflow
Solution 4 - Objective CkoiraView Answer on Stackoverflow