

ブリッジヘッダーを作成し、swiftからObjectiveCのメソッドが動くことを確認できました。

TestProvider.swift

[code]

    import NetworkExtension
    //@objc(TestProvider)
    class TestProvider: NEAppPushProvider {
        
        override init() {
            super.init()
        }
        
        // MARK: - NEAppPushProvider Life Cycle
        override func start(completionHandler: @escaping (Error?) -> Void) {
            completionHandler(nil)
        }
        
        override func stop(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
            completionHandler()
            NSLog("end")
        }
    }
    
[/code]

ブリッジヘッダー  
TestProvider-Bridging-Header.h

[code]

    #ifndef TestProvider_Bridging_Header_h
    #define TestProvider_Bridging_Header_h
    
    #import "TestObjC.h"
    
    #endif /* TestProvider_Bridging_Header_h */
    
[/code]

Objective-Cのヘッダー  
TestObjC.h

[code]

    #ifndef TestObjC_h
    #define TestObjC_h
    
    #import <Foundation/Foundation.h>
    
    @interface TestObjC : NSObject
    - (void) printTest;
    
    @end
    
    #endif /* TestObjC_h */
    
[/code]

Objective-Cのソース  
TestObjC.mm

[code]

    #include "TestObjC.h"
    ※（１）
    
    @implementation TestObjC {
        
    }
    
    -(void) printTest {
        NSLog(@"printTest");
        
    }
    @end
    
[/code]

printTestの文字列が、コンソールログに出力されていることを確認できました。  
相互に連携したいため、以下をサイトを参考にしました。

<https://qiita.com/edo_m18/items/861d090a5471f4f0eeae>

TestProvider.swift

[code]

    import NetworkExtension
    @objc(TestProvider)
    class TestProvider: NEAppPushProvider {
        
        override init() {
            super.init()
        }
        
        // MARK: - NEAppPushProvider Life Cycle
        override func start(completionHandler: @escaping (Error?) -> Void) {
            completionHandler(nil)
        }
        
        override func stop(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
            completionHandler()
            NSLog("end")
        }
    
        // ファクトリメソッドを定義しておく
        class func create() -> TestProvider {
            return TestProvider()
        }
        @objc func doMethod() -> () {
            NSLog("start")
        }
    }
    
[/code]

ビルドできたので、次にObjective-C側にコードを追加したのですが、Testが見つからないとエラーとなってしまいました。  
  
TestObjC.mm

[code]

    #include "TestObjC.h"
    
    @implementation TestObjC {
    
    }
    
    -(void) printTest {
        NSLog(@"printTest");
        TestProvider *test = [TestProvider create];※
    
    }
    @end
    
[/code]

※のTestProvider箇所２箇所で以下のエラーが出てしまします。

> Unknown type name 'TestProvider'  
>  どのように連携させたらいいのか悩んでおります。  
>  何かいいアドバイスがあればよろしくお願いいたします。

＃ご指摘いただいた通りコードが不正でしたので修正しました

次に、swiftのヘッダーを追加すればいいのではと、TestObjC.mm側の※（１）に#import "TestProvider-
Swift.h"を入れてみたのですが、以下のような注意が出ており、

  1. In file included from /Users/ホゲ/Desktop/test/test/TestObjC.mm:10:  
TestProvider-Swift.hを見ると

[code]

    SWIFT_CLASS("_TtC17TestProvider17TestProvider")
    @interface Test : NEAppPushProvider ※１
    - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
    - (void)startWithCompletionHandler:(void (^ _Nonnull)(NSError * _Nullable))completionHandler;
    - (void)stopWithReason:(NEProviderStopReason)reason completionHandler:(void (^ _Nonnull)(void))completionHandler; ※２
    - (void)doMethod;
    @end
    
[/code]

※１箇所に  
「Cannot find interface declaration for 'NEAppPushProvider', superclass of
'TestProvider'」  
※２箇所に  
「Expected a type]  
のエラーが出ておりました。

TestProvider.swiftで継承しているNEAppPushProviderが、swiftとObjectiveCで型が違うため怒られている気もするのですが、どのように連携させたらいいのか悩んでおります。  
何かいいアドバイスがあればよろしくお願いいたします。


CC BY-SA 4.0
2021-04-29T05:54:40.817
75571
2021-05-09T14:07:54.143
2021-05-09T07:29:50.623
44177
44177
question
swift objective-c swift5
Swift5とObjective-Cを相互連携させたい


ご質問内容の修正ありがとうございました。最新のXcode12.5で試したところ、ご記載の内容と発生した事象がほぼ一致(※)しましたので、回答を書かせていただきます。

(※ TestProvider-Swift.h の`@interface`部は、`@interface Test`ではなく、`@interface
TestProvider`になるはずです。)

> TestObjC.mm側の※（１）に#import "TestProvider-Swift.h"を入れてみた

Swiftのコードを使うObjective-
Cのコードに入れるSwiftヘッダのimportを書く位置はその場所(実装ファイル側の他のimport/includeの後)で構いません。

> ※１箇所に  
>  「Cannot find interface declaration for 'NEAppPushProvider', superclass of
> 'TestProvider'」

通常は、上記の位置にヘッダをimportすればOKなのですが、ご質問のように **Objective-C++** ファイルの場合、ヘッダ内の`@import
NetworkExtension;`の部分が有効にならず、記載されたようなエラーになってしまうようです。ご自身で関連するimportを追加してやってください。

### TestObjC.mm

[code]

    #include "TestObjC.h"
    #import <NetworkExtension/NetworkExtension.h> // <-
    #import "TestProvider-Swift.h"
    
    //...
    
[/code]

(特にC++の機能を使用している部分は無いようですが、意図的にObjective-C++としてコンパイルさせたい部分がどこかにあるのでしょうか?)

* * *

また、Objective-C側から使いたいSwiftのメソッド・プロパティには全て`@objc`を付けてやらないといけません。

### TestProvider.swift

[code]

    //...
        @objc class func create() -> Test { // <-
            return Test()
        }
    //...
    
[/code]

* * *

なお、現在のXcodeには若干のバグがあるようで、Swiftヘッダ中の一部にエラーが表示されると、importを追加するなどしてエラーを解消してビルドが成功しても、そのエラー表示が消えないことがあるようです。Build
Succeededと表示されれば問題ないので無視してください。  
(確実に消す方法はわからなかったのですが、いつのまにか消えていました。)


CC BY-SA 4.0
2021-05-09T14:07:54.143
75750
2021-05-09T14:07:54.143
13972
75571
answer