77

I am migrating a UIViewController class to train a bit with Swift. I am successfully using Objective-C code via the bridging header but I have the need of importing a constants file that contains #define directives.

I have seen in Using Swift with Cocoa and Objective-C (Simple macros) the following:

Simple Macros

Where you typically used the #define directive to define a primitive constant in C and Objective-C, in Swift you use a global constant instead. For example, the constant definition #define FADE_ANIMATION_DURATION 0.35 can be better expressed in Swift with let FADE_ANIMATION_DURATION = 0.35. Because simple constant-like macros map directly to Swift global variables, the compiler automatically imports simple macros defined in C and Objective-C source files.

So, it seems it's possible. I have imported the file containing my constants into the bridging header, but I have no visibility from my .swift file, cannot be resolved.

What should I do to make my constants visible to Swift?

UPDATE:

It seems working with NSString constants, but not with booleans:

#define kSTRING_CONSTANT @"a_string_constant" // resolved from swift
#define kBOOL_CONSTANT YES // unresolved from swift
atxe
  • 5,029
  • 2
  • 36
  • 50

5 Answers5

66

At the moment, some #defines are converted and some aren't. More specifically:

#define A 1

...becomes:

var A: CInt { get }

Or:

#define B @"b"

...becomes:

var B: String { get }

Unfortunately, YES and NO aren't recognized and converted on the fly by the Swift compiler.

I suggest you convert your #defines to actual constants, which is better than #defines anyway.

.h:

extern NSString* const kSTRING_CONSTANT;
extern const BOOL kBOOL_CONSTANT;

.m

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

And then Swift will see:

var kSTRING_CONSTANT: NSString!
var kBOOL_CONSTANT: ObjCBool

Another option would be to change your BOOL defines to

#define kBOOL_CONSTANT 1

Faster. But not as good as actual constants.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
  • May I know the reason you use NSString! and not String! ? – Ricky Jul 02 '14 at 03:55
  • 1
    I think it is because you never have to test if a constant is nil before using it, so it is "safe" to unwrap it when used. However I would have let NSString but I am not that confortable with swift at this time :) – foOg Aug 06 '14 at 08:37
  • I suppose `#define`s and `const`s become constants: i.e. `let`s – Tim Nov 26 '15 at 15:01
  • https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html – Jose Manuel Abarca Rodríguez Dec 21 '15 at 20:23
  • How does one pass in constants via -DCONSTANT=val on the command line or xcode plist build settings if we change them to let declarations. It kinda misses the whole point of them really. – Shayne Jun 26 '19 at 05:16
22

Just a quick clarification on a few things from above.

Swift Constant are expressed using the keywordlet

For Example:

let kStringConstant:String = "a_string_constant"

Also, only in a protocol definition can you use { get }, example:

protocol MyExampleProtocol {
    var B:String { get }
}
pkamb
  • 33,281
  • 23
  • 160
  • 191
Joshua
  • 221
  • 1
  • 2
8

In swift you can declare an enum, variable or function outside of any class or function and it will be available in all your classes (globally)(without the need to import a specific file).

  import Foundation
  import MapKit

 let kStringConstant:String = "monitoredRegions"

  class UserLocationData : NSObject {    
class func getAllMonitoredRegions()->[String]{
     defaults.dictionaryForKey(kStringConstant)
 }
Ankish Jain
  • 11,305
  • 5
  • 36
  • 34
  • 1
    Do you think it is necessary to declear the type of `kStringConstant` which can be inferred by the content provided, `"monitoredRegins"`. – XY L Feb 14 '15 at 05:55
  • Nope not really. Its just a coding practice , any hardcoded string I like to put it on top. Later easily move it out to a constants file. – Ankish Jain Dec 09 '15 at 08:52
0

simple swift language don't need an macros all #define directives. will be let and complex macros should convert to be func

Amr Angry
  • 3,711
  • 1
  • 45
  • 37
  • 1
    Yes you are correct, [Using Imported C Macros in Swift](https://developer.apple.com/documentation/swift/imported_c_and_objective-c_apis/using_imported_c_macros_in_swift) – Anirudha Mahale Nov 23 '18 at 05:17
0

The alternative for macro can be global variable . We can declare global variable outside the class and access those without using class. Please find example below

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

class test {

}
Ankur Lahiry
  • 2,253
  • 1
  • 15
  • 25
garg
  • 2,651
  • 1
  • 24
  • 21