Objective-C accessing Swift Package functions
You declared
public func sayHello() {
print(text)
}
That makes the method sayHello
public across module, but it does not expose it to Objective-C. Instead:
@objc public func sayHello() {
print(text)
}
I added Objective-C files to Swift package via modulemap file, but implementation wasn't connected
You don't need to use systemLibrary
target with a modulemap
file for your own ObjC source files because usually it's used as wrapper to available C system libraries such as sqlite3
, curl
etc. and the modulemap
file can be created for your target automatically by XCode.
So you can use simple target
:
...
targets: [
...
.target(name: "DataDeflate", path: "Sources/ObjC/DataDeflate"),
]
...
Next you should organise your files inside DataDeflate folder next way:
- Package.swift
+ Sources
+ ObjC
+ DataDeflate
+ include
- DataDeflate.h
- NSData+Deflate.h
- NSData+Deflate.m
...
Where include
subfolder must contain <YourTargetName>.h
(DataDeflate.h) file and all other public headers to include.
How to use a swift module in an objective-c module with SwiftPM?
Right now it's not possible to import Swift module in C module, it only works another way around, import C into Swift.
You can find detailed information at SwiftPM - C language targets
Accessing Swift Extension From Objective-C
It is easy enough using simply a Dictionary
20> extension Dictionary {
21. func toJSONString () -> String { return "my dictionary" }
22. }
23> ["a": 1, "b": 2].toJSONString()
$R10: String = "my dictionary"
The Apple documentation does not mention using extensions on Objective-C classes.
How do I call Objective-C code from Swift?
Using Objective-C Classes in Swift
If you have an existing class that you'd like to use, perform Step 2 and then skip to Step 5. (For some cases, I had to add an explicit
#import <Foundation/Foundation.h
to an older Objective-C File.)
Step 1: Add Objective-C Implementation -- .m
Add a .m
file to your class, and name it CustomObject.m
.
Step 2: Add Bridging Header
When adding your .m
file, you'll likely be hit with a prompt that looks like this:
Click Yes!
If you did not see the prompt, or accidentally deleted your bridging header, add a new .h
file to your project and name it <#YourProjectName#>-Bridging-Header.h
.
In some situations, particularly when working with Objective-C frameworks, you don't add an Objective-C class explicitly and Xcode can't find the linker. In this case, create your .h
file named as mentioned above, then make sure you link its path in your target's project settings like so:
Note:
It's best practice to link your project using the $(SRCROOT)
macro so that if you move your project, or work on it with others using a remote repository, it will still work. $(SRCROOT)
can be thought of as the directory that contains your .xcodeproj file. It might look like this:
$(SRCROOT)/Folder/Folder/<#YourProjectName#>-Bridging-Header.h
Step 3: Add Objective-C Header -- .h
Add another .h
file and name it CustomObject.h
.
Step 4: Build your Objective-C Class
In CustomObject.h
#import <Foundation/Foundation.h>
@interface CustomObject : NSObject
@property (strong, nonatomic) id someProperty;
- (void) someMethod;
@end
In CustomObject.m
#import "CustomObject.h"
@implementation CustomObject
- (void) someMethod {
NSLog(@"SomeMethod Ran");
}
@end
Step 5: Add Class to Bridging-Header
In YourProject-Bridging-Header.h
:
#import "CustomObject.h"
Step 6: Use your Object
In SomeSwiftFile.swift
:
var instanceOfCustomObject = CustomObject()
instanceOfCustomObject.someProperty = "Hello World"
print(instanceOfCustomObject.someProperty)
instanceOfCustomObject.someMethod()
There is no need to import explicitly; that's what the bridging header is for.
Using Swift Classes in Objective-C
Step 1: Create New Swift Class
Add a .swift
file to your project, and name it MySwiftObject.swift
.
In MySwiftObject.swift
:
import Foundation
@objc(MySwiftObject)
class MySwiftObject : NSObject {
@objc
var someProperty: AnyObject = "Some Initializer Val" as NSString
init() {}
@objc
func someFunction(someArg: Any) -> NSString {
return "You sent me \(someArg)"
}
}
Step 2: Import Swift Files to ObjC Class
In SomeRandomClass.m
:
#import "<#YourProjectName#>-Swift.h"
The file:<#YourProjectName#>-Swift.h
should already be created automatically in your project, even if you can not see it.
Step 3: Use your class
MySwiftObject * myOb = [MySwiftObject new];
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
myOb.someProperty = @"Hello World";
NSLog(@"MyOb.someProperty: %@", myOb.someProperty);
NSString * retString = [myOb someFunctionWithSomeArg:@"Arg"];
NSLog(@"RetString: %@", retString);
Notes:
If Code Completion isn't behaving as you expect, try running a quick build with ⌘⇧R to help Xcode find some of the Objective-C code from a Swift context and vice versa.
If you add a
.swift
file to an older project and get the errordyld: Library not loaded: @rpath/libswift_stdlib_core.dylib
, try completely restarting Xcode.While it was originally possible to use pure Swift classes (Not descendents of
NSObject
) which are visible to Objective-C by using the@objc
prefix, this is no longer possible. Now, to be visible in Objective-C, the Swift object must either be a class conforming toNSObjectProtocol
(easiest way to do this is to inherit fromNSObject
), or to be anenum
marked@objc
with a raw value of some integer type likeInt
. You may view the edit history for an example of Swift 1.x code using@objc
without these restrictions.
Swift Package Manager fails to build Objective-C package when public headers use angle bracket () #imports
I had the same issue recently. The only way I found to work around this was to change the includes to standard user-style includes
#import "ORSSerialPacketDescriptor.h"
Of course, this breaks the header for Objective-C clients. But since Swift uses the module map, you can still use it from Swift code.
Related Topics
Siri Remote's Menu Button Not Exiting Application When UIbutton Is Focused
Scan for Ble Devices and Present Them in an UItableview
Skipnext Skipprevious Google Cast Greyed Out
Generating a Simple Algebraic Expression in Swift
Didbegincontact Not Being Called Swift
Optional in Swift, Return Count of Array
Access Safari Bookmarks in Macos Mojave Programmatically
Indent Second Line of UIlabel (Swift)
Pass Data from Tableviewcontroller to Another Tableviewcontroller in Swift
Could Not Find an Overload for '-' That Accepts The Supplied Arguments
Osx/Swift: Call a Function When Internet Connection Is Established/Restored
Swiching Between 2 Diferent Nsviewcontrollers with Data
Watchkit Extension Cannot Read from Icloud
Allow Line Editing When Reading Input from The Command Line
Why Extensions Cannot Add Stored Properties