如何在Swift中使用Objective-C的#define

77
我正在将一个UIViewController类迁移到Swift语言。我已经通过桥接头文件成功使用了Objective-C代码,但我需要导入一个包含#define指令的常量文件。
Using Swift with Cocoa and Objective-C(简单宏)中,我看到了以下内容:

简单宏

在C和Objective-C中,您通常使用#define指令来定义原始常量,在Swift中则使用全局常量。例如,常量定义#define FADE_ANIMATION_DURATION 0.35可以用Swift更好地表示为let FADE_ANIMATION_DURATION = 0.35。因为简单的类似常量的宏直接映射到Swift全局变量,编译器会自动导入在C和Objective-C源文件中定义的简单宏。

所以,这似乎是可能的。我已经将包含我的常量的文件导入到桥接头文件中,但是在我的.swift文件中无法访问,无法解决。
我该怎么做才能让我的常量在Swift中可见?
更新:
似乎可以使用NSString常量,但不能使用布尔值:
#define kSTRING_CONSTANT @"a_string_constant" // resolved from swift
#define kBOOL_CONSTANT YES // unresolved from swift

1
尝试使用 true 而不是 YES。 - David Berry
5个回答

66

目前,一些#define已被转换,而另一些则未被转换。更具体地说:

#define A 1

...变成:

var A: CInt { get }

或者:
#define B @"b"

...变为:

var B: String { get }

遗憾的是,YESNO无法被Swift编译器即时识别和转换。

我建议您将#define转换为实际常量,这比使用#define更好。

.h文件:

extern NSString* const kSTRING_CONSTANT;
extern const BOOL kBOOL_CONSTANT;

.m

NSString* const kSTRING_CONSTANT = @"a_string_constant";
const BOOL kBOOL_CONSTANT = YES;

然后 Swift 就会看到:

var kSTRING_CONSTANT: NSString!
var kBOOL_CONSTANT: ObjCBool

另一个选择是将您的BOOL定义更改为

#define kBOOL_CONSTANT 1

更快,但不如实际常量好。

我可以知道你为什么使用NSString!而不是String!吗? - Ricky
1
我认为这是因为在使用常量之前不需要测试它是否为空,因此在使用时解包是“安全”的。但是,我会选择使用NSString,只是目前对Swift不太熟悉 :) - foOg
我认为#defineconst变成了常量:即lets。 - Tim
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html - Jose Manuel Abarca Rodríguez
如何通过命令行或Xcode plist构建设置通过-DCONSTANT=val传递常量,如果我们将它们更改为let声明,那么这有点失去了它们的全部意义。 - Shayne

22

关于上面的几点,我想简单澄清一下。

使用let关键字可以表示Swift常量。

例如:

let kStringConstant:String = "a_string_constant"

此外,只有在协议定义中才能使用{ get },例如:
protocol MyExampleProtocol {
    var B:String { get }
}

8
在Swift中,你可以在任何类或函数之外声明一个枚举、变量或函数,并且它将在所有类中都可用(全局范围),无需导入特定文件。
  import Foundation
  import MapKit

 let kStringConstant:String = "monitoredRegions"

  class UserLocationData : NSObject {    
class func getAllMonitoredRegions()->[String]{
     defaults.dictionaryForKey(kStringConstant)
 }

1
你认为是否有必要声明 kStringConstant 的类型,因为它可以通过提供的内容 "monitoredRegins" 推断出来。 - XY Li
不是真的。这只是一种编码惯例,我喜欢把任何硬编码字符串放在顶部。稍后可以轻松地将其移动到常量文件中。 - Ankish Jain

0

简单的Swift语言不需要宏定义指令。所有的 #define 指令都将被替换为 let,而复杂的宏定义应该转换为函数。


1
是的,你说得对,在 Swift 中使用导入的 C 宏 - Anirudha Mahale

-1

替代宏的选择可以是全局变量。 我们可以在类外声明全局变量,并在不使用类的情况下访问它们。 请参见以下示例:

import Foundation
let BASE_URL = "www.google.com"

class test {

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接