65

if I declare the swift constant as a global constant like:

let a = "123"

but the a cannot be found in objective c.

How to solve this?

Iulian Onofrei
  • 9,188
  • 10
  • 67
  • 113
user2909913
  • 4,149
  • 5
  • 16
  • 11
  • how did you import that swift file which declares global constant in objective c file? – BaSha Jun 16 '14 at 05:42
  • as document said:https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/buildingcocoaapps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-XID_77 #import "ProductModuleName-Swift.h” – user2909913 Jun 16 '14 at 05:50
  • something weird, if I go inside my ProductModuleName-Swift.h, I can see my global variable defined as objective c property under @interface but can not use it! – BaSha Jun 16 '14 at 06:15

6 Answers6

43

Swift code:

public class MyClass: NSObject {
    public static let myConst = "aConst"
}

and then in Objective-C:

[MyClass myConst]

Isn't this working as well? As in this works for me.

Also this is somewhat shorter as creating a object first (alloc, init). Making a new function for every constant is... not pretty :/

Update for Swift 4

Because of the changes in Swift 4's Objective-C inference, you need to add the @objc annotation to the declared constant as well. The previous declaration then becomes:

@objcMembers
public class MyClass: NSObject {
    public static let myConst = "aConst"
}

The calling Objective-C code remains the same.

Using @objcMembers makes all constants available (as if you'd write @objc before each constant), but I've had times where the compiler somehow wouldn't generate the corresponding ObjC code.

In those cases I'd suggest adding the @objc decorator before the constant as well.
I.e.: @objc public static let myConst = "aConst"

Community
  • 1
  • 1
Gerald Eersteling
  • 1,244
  • 14
  • 28
42

From Apple Doc:

You’ll have access to anything within a class or protocol that’s marked with the @objc attribute as long as it’s compatible with Objective-C. This excludes Swift-only features such as those listed here:

  1. Generics
  2. Tuples
  3. Enumerations defined in Swift
  4. Structures defined in Swift
  5. Top-level functions defined in Swift
  6. Global variables defined in Swift
  7. Typealiases defined in Swift
  8. Swift-style variadics
  9. Nested types
  10. Curried functions

Therefore its not possible to access global variables(Constants) or global functions defined in Swift.

Possible Solutions:

  1. From the Apple Document Swift programming language, You can Declare Type Properties as

    class var constant: Int =  {
        return 10
    }()
    

    But currently in Swift(beta-3) Type properties are not supported.

  2. You can declare a Class function to get a constant value:

    In Swift:

    class func myConst() -> String {
    
        return "Your constant"
    }
    

Accessing from Objective-C:

 NSString *constantValue = [ClassName myConst];
 NSLog(@"%@", constantValue);
toddg
  • 2,863
  • 2
  • 18
  • 33
Yatheesha
  • 10,412
  • 5
  • 42
  • 45
  • 1
    Then how should I do if I want to define some constants in Swift and want to use it in Objective c? – user2909913 Jun 16 '14 at 06:54
  • 1
    Wow apple... so much for interoperability. More like have to write hacky classes in swift for every nice thing that swift can do naturally. Apple please fix this – Tim Dec 29 '15 at 04:47
  • I think you are assuming that the project is a Objective C project. But if my project is a Swift project, In Objective C class, I want use a variable that defined in swift file, How should I do? – DàChún Feb 17 '16 at 12:21
  • Thanks for the list of swift things that's not compatible with Objective C – Durai Amuthan.H Jun 20 '16 at 15:13
7

You should not have any problem by using let in Objective-C, next example was made with Xcode 7.2 :

MyClass.swift

import Foundation
import UIKit
@objc class MyClass : NSObject { // <== @objc AND NSObject ARE BOTH NECESSARY!!!
let my_color = UIColor( red:128/255,green:32/255,blue:64/255,alpha:1 ) // <== CONSTANT!!!
}

MyObjectiveC.m

#import "PROJECTNAME-Swift.h" // <== NECESSARY TO RECOGNIZE SWIFT CLASSES!!!
@interface MyObjectiveC ()
@end
@implementation MyObjectiveC
@synthesize tableview; // <== ANY UI OBJECT, JUST AS EXAMPLE!!!
- (void) viewDidLoad () {
MyClass * mc = [ [ MyClass alloc ] init ]; // <== INSTANTIATE SWIFT CLASS!!!
tableview.backgroundColor = mc.my_color;   // <== USE THE CONSTANT!!!
}
@end

PROJECTNAME is the name of your Xcode project, as shown in Project Navigator.

  • thanks @Jose Manuel Abarca Rodríguez, but I don't have the "PROJECTNAME-Swift.h", should I create one? – DàChún Feb 17 '16 at 08:21
  • @User9527, you don't have to create it, it's a Swift's directive, you just type it and the compiler will know what to do (which is to recognize Swift code from Objective C code). – Jose Manuel Abarca Rodríguez Feb 18 '16 at 16:27
  • 1
    yes thank you, adding @objc to the class is the correct answer here, you do not want to make a func for every constant like the other answer that would be a giant PITA – naomimichiko Apr 18 '16 at 17:41
1

In your swift class,

let constant: Float = -1
class YourClass: NSObject {
class func getMyConstant() -> Float {return constant}
...
}

Clean, build to let xcode prepare this method useable for obj-c. Then at your obj-c class

if ([YourClass getMyConstant] != 0) {
...
}
Sourabh Sharma
  • 8,222
  • 5
  • 68
  • 78
alicanbatur
  • 2,172
  • 1
  • 28
  • 36
1

First of all you need to know about the important of auto-generated Swift header file.

It is the one that will made the magic to transcribe the Swift code to be understandable from Objective-C.

This file is auto-generated by Xcode (do not look for it in your project).

The important of this file is to use the correct name, it can match with your target name, but, may not, it is the product module name. (Search for it in your project settings as "Product module")

You need to import this file on the Objective-C class that you want to use a Swift class and also the Swift class name of your Swift file.

#import <ProductModuleName-Swift.h>
@class MySwiftClassName;

My Swift class should have the prefix @objc and inherit from NSObject:

@objc class MySwiftClassName: NSObject {
   let mySwiftVar = "123"
}

Then you can call your Swift variable from the Objective-C file:

MySwiftClassName *mySwiftClassO = [[MySwiftClassName alloc] init];
NSString *myVar = mySwiftClassO.mySwiftVar;

Make sure to clean and rebuild your project after each change to force regenerate this auto-generated file.

If your Swift header file was auto-generated correctly you can navigate to it by clicking over the import file name and check if all the code you need was properly transcribed.

In the following post you can find more detailed information about this. https://solidgeargroup.com/bridging-swift-objective-c

nasli
  • 46
  • 7
0

Classes func don't work. The only solution I have found out is this one:

class YourController: NSObject {

@objc static let shared = YourController()

private override init() { }

@objc class func sharedInstance() -> YourController {
    return YourController.shared
}

@objc let terms = "Your-String-here"

And then on Obj-c file:

[[YourController sharedInstance].terms]
oskarko
  • 3,382
  • 1
  • 26
  • 26