如何在 Objective-C 中使用 Swift 结构

简单地说,我有一个 struct,它存储应用程序常量如下:

struct Constant {


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


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

例如,可以在 Swift 代码中通过调用 Constant.ParseClientKey来使用这些常量。但是在我的代码中,它还包含一些 Objective-C 类。所以我的问题是如何在 Objective-C 代码中使用这些常量?

如果这种声明常量的方法不好,那么创建可在 Swift 和 Objective-C 代码中使用的全局常量的最佳方法是什么?

67520 次浏览

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

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.

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

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"