简体   繁体   中英

I added Objective-C files to Swift package via modulemap file, but implementation wasn't connected

I have a Swift package, and try to add Objective-c files.

My package now:

Root
- Package.swift
+ Sources
  + ObjC
    + DataDeflate
      - DataDeflate.h
      - module.modulemap
      - NSData+Deflate.h
      - NSData+Deflate.m
  + Swift
    + DataDeflator
      - DataDeflatow.swift
+ Tests
  + DataDeflatorTests
    - DataDeflatorTests.swift

Package.swift content:

import PackageDescription

let package = Package(
    name: "DataDeflator",
    products: [
        .library(name: "DataDeflator", targets: ["DataDeflator"]),
    ],
    targets: [
        .target(
            name: "DataDeflator",
            dependencies: ["DataDeflate"],
            path: "Sources/Swift/DataDeflator"),
        .systemLibrary(name: "DataDeflate", path: "Sources/ObjC/DataDeflate"),
        .testTarget(
            name: "DataDeflatorTests",
            dependencies: ["DataDeflator"]),
    ]
)

module.modulemap content:

module DataDeflate [system] {
  header "DataDeflate.h"
  link "DataDeflate"
  export *
}

DataDeflate.h content:

#ifndef DataDeflate_h
#define DataDeflate_h

#import "NSData+Deflate.h"

#endif /* DataDeflate_h */

Now, using these settings ( module.modulemap and targets in Package.swift ), Swift code has access to Objective-C NSData category. But only for declaration ( NSData+Deflate.h ), and not to implementation ( NSData+Deflate.m )!

When I add Objective-C method calling, it builds successfully, without any warnings. But unrecognized selector sent to instance error appears when unit tests runs.

What did I forget? How can I connect both declaration and implementation from Objective-C to Swift?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM