I'm trying to use a swift classes methods from my objective-c .m file but I can't get my file to import.
In Build Settings -> Packaging I have: Defines Module YES
my Product Module Name is Library
In Build Options I have set Embedded Content Contains Swift Code as YES
However, when I attempt to import the target module to my *.m file I get file not found error.
#import "Library-Swift.h"
Fails to import.
I have swift files. Any ideas?
I'm also trying to use `"Library-Bridging-Header.h"
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "PLAddBookViewController.h"
..but it doesn't seem to be doing anything.
You can expose your Swift class to ObjC in 2 ways:
class MySwiftClass : NSObject { // inherit from any ObjC class
}
#objc class MyClassClass { // tell the compiler to expose it to ObjC
}
From the Swift book:
When you define a Swift class that inherits from NSObject or any other Objective-C class, the class is automatically compatible with Objective-C. If your Swift class does not derive from an Objective-C class and you want to use an API from that class in Objective-C code, you can use the #objc attribute described below.
The #objc attribute makes your Swift API available in Objective-C and the Objective-C runtime. In other words, you can use the #objc attribute before a Swift method, property, subscript, initializer, class, protocol, or enumeration to use it from Objective-C code.
Related
I have a class that is defined in Swift:
// SwiftClass.swift
#objc
class SwiftClass: NSObject {
// ...
}
An Objective-C class can inherit from that Swift class:
// ObjCObject.h
#import "MyModule-Swift.h"
#interface ObjCObject: SwiftClass
// ...
#end
However, when doing so, I cannot use that class in Swift code anymore.
To use it in Swift, I have to add it to the bridging header:
// MyModule-BridgingHeader.h
#import "ObjCObject.h"
as only classes referenced by the bridging header are visible to Swift code. And this creates a cyclic reference, as the bridging header must be processed prior to compiling the Swift source code yet the generated Swift header (MyModule-Swift.h) only exists after compiling the Swift source code and thus won't exist when the bridging header is being processed.
If it was just for method arguments, I could use forward declarations but an Obj-C class cannot inherit from a forward declared class.
So am I just missing something here or is it really the case that you can use Obj-C classes in Swift and Swift classes in Obj-C but you cannot use an Obj-C class in Swift if it inherits from a Swift class?
I have a project that was started in Objective-C, and I am trying to import some Swift code into the same class files that I have previously written Objective-C in.
I need exclude Swift classes from <MyProject>-swift.h
for example exclude LoginVC
Only the swift class with #objc will generate objective-c interface in Project-swift.h.
By adding #objc, your swift class will be visible by others objective-c class.
Example :
#objc class LoginVC : UIViewController{ //will be present in Project-swift.h
class LoginVC : UIViewController{ //will not be present in Project-swift.h
I'm trying to use Swift class in my Objective-C file.
I included "moduleName-Swift.h" file in my SuperViewController.m file, but when I try to declare a public method in SuperViewController.h with Swift-class as method parameter, I obviously get an error: "Expected a type"
How can I use swift-class in a header file if I can only include projectModule-Swift.h in .m files??
Make sure to put #objc before the swift class name.
#objc myclassname { ... }
Also add
#class myclassname;
in your obj-c header file where you want to access the swift class
Remember to import the project generated swift header file in your source file, for example #import <MyProjectName-Swift.h>
I had the same problem. Adding #class MyClassName in obj-c .h file created the "Receiver 'MyClassName' for class message is a forward declaration" error, so I deleted that and ONLY added the "#objc" before the swift class name, BUT I also had to make sure that the swift class is a subclass of NSObject.
#objc class MySwiftClass:NSObject { ... }
WITHOUT #class MyClassName in obj-c .h file!
I had to use:
#obj public class MySwiftClass: NSObject { ... }
I created a class with no subclass, adding #objc and #objcmembers did not work.
After I change do :NSObject the entire class turn visible to objective-C
I searched some posts, I think I cannot write an extension under Swift, and call it from Objective-C code, right?
#objc like attributes only support methods, class, protocols ?
You can write a Swift extension and use it in Objective-C code. Tested with Xcode 6.1.1.
All you need to do is:
create your extension in Swift (#objc annotation needed since Swift 4.0.3)
#import "ProjectTarget-Swift.h" in your Objective-C class (where "ProjectTarget" represents the XCode target the Swift extension is associated with)
call the methods from the Swift extension
I found out that in Swift 4.0 I had to add #objc in front of my extension keyword in order for the Swift extension methods to become visible by an instance of the Objc class I was extending.
In short:
File configuration setup:
CustomClass.h
CustomClass.m
CustomClassExtension.swift
In CustomClassExtension:
#objc extension CustomClass
{
func method1()
{
...
}
}
In my AppDelegate.m:
self.customClass = [[CustomClass alloc] init];
[self.customClass method1];
This solution works for Swift 2.2 and Swift 3. Note that only extensions for classes (not for structs or enums) will be accessible from Objective-C.
import UIKit
extension UIColor {
//Custom colours
class func otherEventColor() -> UIColor {
return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
}
}
Then #import "ProductModuleName-Swift.h" in your ObjC file.
Swift 4
extension UIColor {
// As of Swift 4.0.3, the #objc annotation is needed if you want to use the extension in Objective-C files
#objc
class func otherEventColor() -> UIColor {
return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
}
}
As covered in the other answers, importing the generated Swift header works in most cases.
An exception to this is when the category is defined on a bridged type (i.e. the extension is defined on String and not NSString). These categories will not automatically be bridged to their Objective-C counterparts. To get around this, you'll either need to use the Objective-C type (and cast the return value in your Swift code with as String) or define an extension for both the Swift and Objective-C types.
Import "#import "ProductModuleName-Swift.h" header in objective-c file and add #objc infront of your extentsion in swift file. It will working fine in swift 4.2 and swift 5
If think you have configured everything correctly (marked your Swift entities with #objcMembers or #objc, imported the bridging header "ProductModuleName-Swift.h" and so on) – but still getting the No visible #interface for 'FooClass' declares the selector 'fooSelector' error:
Check if you see your interfaces in the bridging header by ctrl + cmd clicking on it. If you don't, check out my answer to this question: Swift to Objective-C header does not contain Swift classes
I have defined two Swift classes in my Xcode project. Everything else is Objective-C.
To use the classes in Objective-C I'm trying to import ProductModuleName-Swift.h but the file contains only the definition for one of the Swift classes. (SearchViewController)
This class is being exported:
class SearchViewController : UIViewController {
but this isn't:
public class Socket {
From "Migrating Your Objective-C Code to Swift" in the "Using Swift with Cocoa and Objective-C" documentation:
To be accessible and usable in Objective-C, a Swift class must be a descendant of an Objective-C class or it must be marked #objc.
When you bring Swift code into Objective-C, remember that Objective-C won’t be able to translate certain features that are
specific to Swift. For a list, see "Using Swift from
Objective-C".
SearchViewController is a descendent of an Objective-C class, but Socket is not.
To make it usable in Objective-C, declare it as a subclass of NSObject:
public class Socket : NSObject { ...
or declare it as
#objc public class Socket { ...