web-dev-qa-db-ja.com

Swiftフレームワークにプライベートフレームワークヘッダーをインポートする方法は?

一部のパブリックヘッダーと一部のプライベートヘッダーを公開するObjective-Cフレームワーク(フレームワークA)があります。パブリックヘッダーは、フレームワークのアンブレラヘッダーでも宣言されます。 Objective-Cフレームワークにリンクする2番目のSwiftフレームワーク(フレームワークB))があります。

ここで、AのパブリックヘッダーをBにインポートする場合は、import A

しかし、プライベートヘッダーをインポートするにはどうすればよいですか?

ブリッジングヘッダーはフレームワークでサポートされていないため、オプションではないことを知っています。プライベートヘッダー用に別のアンブレラヘッダーを作成する必要がありますか?

20
Mihai Damian

フレームワークAを変更して、プライベートモジュールをエクスポートする必要があります。

  1. Aプロジェクトに プライベートモジュールマップファイル を作成します。これは次のようになります。

    A/private.modulemap

    explicit module A.Private {
    
        // Here is the list of your private headers.
        header "Private1.h"
        header "Private2.h"
    
        export *
    }
    
  2. フレームワークAターゲットの「ビルド設定」で、「プライベートモジュールマップファイル」の行を検索し、次のようにします。

    $(SRCROOT)/A/private.modulemap
    
  3. 「ソースのコンパイル」にprivate.modulemapファイルを含めないでください。それは不必要な警告を引き起こします。

  4. フレームワークAターゲットをクリーンアップしてビルドします。

  5. フレームワークB Swiftファイル。このようにプライベートモジュールをインポートできます。

    import A
    import A.Private
    
26
rintaro

この質問が投稿されてからしばらく経ちました。受け入れられた答えは非常によく、私に関する限り、それは一般的なアプローチです。

問題は、実際には「プライベート」ではないことです。フレームワーク内でこれを実行して、「プライベート」部分にアクセスできます。

// Framework A Swift file
import A.Private

ただし、アプリでフレームワークAを使用する場合(またはクライアントに出荷する場合)は、次のことが可能です。

// Client App Swift file
import A
import A.Private

// access "private" framework methods and classes

これを解決しようとしていました。最近、ユーザー(クローズドソースフレームワーク)から非表示にする必要があったためです。SDKの整合性に対する脅威であるため、誰にもアクセスを許可できませんでした。

私はその問題の解決策を見つけましたが、全体としてここに貼り付けるには少し複雑すぎます。

私はそれについて媒体を投稿しませんでした。多分それは誰かがその問題をチェックするのを助けるでしょう、それは私の記事へのリンクです:

https://medium.com/@amichnia_31596/creating-Swift-framework-with-private-objective-c-members-the-good-the-bad-and-the-ugly-4d726386644b

2
Andrzej Michnia

私の状況は私のセットアップに固有である可能性がありますが、誰かに役立つ場合に備えて、ここで提供します。また、私はそれをリンクするSwiftフレームワーク(フレームワークB)で使用する必要があるプライベートヘッダーを備えたObjective-Cフレームワーク(フレームワークA)を持っています。追加の詳細:

  1. 各フレームワークは、ワークスペースの個別のプロジェクトにあります

  2. プロジェクトはCocoaPodsを使用しています

  3. Podspecは、2つのフレームワーク間の次の依存関係を定義します。

    s.subspec 'FrameworkA' do |cs|
        cs.vendored_frameworks = "lib/FrameworkA.framework"
    end
    
    s.subspec 'FrameworkB' do |ts|
        ts.dependency 'FrameworkA'
        ts.vendored_frameworks = "lib/FrameworkB.framework"
    end
    

@rintaroが提供するソリューションは、Xcodeで実行するとうまく機能しますが、ポッドがデプロイされると、FrameworkBは、FrameworkAにあるプライベートモジュールマップのパスを使用してプライベートヘッダーを見つけることができません。私にとってうまくいったのは、プライベートモジュールマップでPrivateHeaders dirへの相対パスを使用することでした:

module FrameworkA_Private {
    header "../FrameworkA.framework/PrivateHeaders/Private.h"
    export *
}

これは、CocoaPodsを使用してインストールされた最終製品のXcode andで機能します。最終ビルド製品のフォルダーを参照するので、少しハックです。CocoaPodsにこれらのパスを保持する方法を伝える他の方法があるとしても驚くことはありませんが、それが何であれ、見つかりませんでした。これで今のところ問題が解決します。

1
Wayne Burkett