108

Xcode 6では、独自の Dynamic を作成できますCocoa Frameworks

ここに画像の説明を入力

なぜなら:

  • シミュレータはまだ32-bitライブラリを使用しています

  • 2015 年 6 月 1 日以降、App Store に送信されるアプリのアップデートには、64 ビットのサポートが含まれ、iOS 8 SDK ( developer.apple.com )でビルドされている必要があります。

デバイスとシミュレータでプロジェクトを実行するには、ファット ライブラリを作成する必要があります。つまり、フレームワークで 32 ビットと 64 ビットの両方をサポートします。

しかし、他のプロジェクトとの将来の統合のためにユニバーサルファットフレームワークをエクスポートする方法(およびこのライブラリを誰かと共有する方法)のマニュアルは見つかりませんでした。

再現するための私の手順は次のとおりです。

  1. ONLY_ACTIVE_ARCH=NOで設定Build Settings

    ここに画像の説明を入力

  2. armv7 armv7s arm64 i386 x86_64サポートを追加するArchitectures(確かに)

ここに画像の説明を入力

  1. Framework をビルドし、Finder で開きます。

ここに画像の説明を入力 ここに画像の説明を入力

  1. このフレームワークを別のプロジェクトに追加します

実結果:

しかし、最終的には、デバイスとシミュレーターでこのフレームワークを使用してプロジェクトを実行することにまだ問題があります。

  • フォルダーからフレームワークをDebug-iphoneos取得すると、デバイスで動作し、シミュレーターでエラーが発生します。ld: symbol(s) not found for architecture i386

      xcrun lipo -info CoreActionSheetPicker
    

    ファット ファイルのアーキテクチャ: CoreActionSheetPicker: armv7 armv7s arm64

  • フォルダーからフレームワークを取得するDebug-iphonesimulatorと、シミュレーターで動作します。デバイスにエラーがあります:ld: symbol(s) not found for architecture arm64

      xcrun lipo -info CoreActionSheetPicker
    

    ファット ファイルのアーキテクチャ: CoreActionSheetPicker: i386 x86_64

では、デバイスやシミュレーターで動作する動的フレームワークを作成するにはどうすればよいでしょうか?

この回答は、Xcode 6 iOS の Cocoa Touch Framework の作成 - アーキテクチャの問題に関連していますが、重複していません。


アップデート:

この場合の「ダーティハック」を見つけました。以下の私の答えを見てください。誰かがもっと便利な方法を知っているなら、教えてください!

4

6 に答える 6

82

この回答の実際は: 2015 年 7 月です。状況が変わる可能性が最も高いです。

TLDR;

現在、Xcode にはユニバーサル ファット フレームワークの自動エクスポート ツールがないため、開発者は手動でlipoツールを使用する必要があります。また、このレーダーによると、フレームワークの消費者である AppStore 開発者に提出する前にlipo、フレームワークからシミュレーター スライスを取り除くためにも使用する必要があります。

より長い答えが続きます


このトピックで同様の調査を行いました(回答の下部にあるリンク)。

xcodebuildの配布に関する公式ドキュメントが見つからなかったので、Apple Developer Forums、Carthage および Realm プロジェクトの調査と、、、、ツールlipoを使用した私自身の実験に基づいて調査しました。codesign

これは、Apple Developer Forums スレッドExporting app with embedded frameworkからの長い引用 (私からの少しのマークアップ付き)です。

フレームワーク プロジェクトからフレームワークをエクスポートする適切な方法は何ですか?

現在、唯一の方法は、まさにあなたが行ったことです:

  • シミュレーターと iOS デバイスの両方のターゲットをビルドします。
  • そのプロジェクトの Xcode の DerivedData フォルダーに移動し、2 つのバイナリを 1 つのフレームワークにまとめます。ただし、Xcode でフレームワーク ターゲットをビルドする場合は、ターゲット設定の [Build Active Architecture Only] を [NO] に調整してください。これにより、Xcode は複数のバイナリ タイプ (arm64、armv7 など) のターゲットをビルドできます。これが、スタンドアロンのバイナリとしてではなく、Xcode からは機能する理由です。

  • また、スキームがリリース ビルドに設定されていることを確認し、リリースに対してフレームワーク ターゲットをビルドする必要があります。ライブラリが読み込まれていないというエラーが引き続き発生する場合は、フレームワークのコード スライスを確認してください。

  • 結果を使用lipo -info MyFramworkBinaryして調べます。

lipo -info MyFrameworkBinary

結果はi386 x86_64 armv7 arm64

  • 最新のユニバーサル フレームワークには 4 つのスライスが含まれますが、さらに含めることもできます。i386 x86_64 armv7 arm64 少なくともこの 4 つが表示されない場合は、Build Active Architecture 設定が原因である可能性があります。

これは、@skywinderが回答で行ったのとほぼ同じプロセスを説明しています。

これは、Carthage が lipoを使用し、Realm が lipoを使用する方法です。


重要な詳細

レーダーがあります: Xcode 6.1.1 & 6.2: シミュレーター スライスを含む iOS フレームワークは App Store に送信できず、それに関する長い議論がRealm#1163Carthage#188で行われ、特別な回避策で終了しました:

AppStore に提出する前に、iOS フレームワークのバイナリをシミュレーターのスライスから取り除く必要があります。

Carthage には特別なコードがあります: CopyFrameworksと対応するドキュメント:

このスクリプトは、ユニバーサル バイナリによって引き起こされるApp Store の送信バグを回避します。

Realm には、 strip-frameworks.sh という特別なスクリプトと、対応するドキュメントがあります。

この手順は、ユニバーサル バイナリをアーカイブするときのApp Store 送信バグを回避するために必要です。

また、良い記事もあります: Stripping Unwanted Architectures From Dynamic Libraries In Xcode

strip-frameworks.shもちろん、誰でもゼロから自由に作成できますが、私自身はRealmを使用しましたが、これは変更なしで完全に機能しました。


この質問の別の側面が含まれているため、読むことをお勧めする私のトピックへのリンク: コード署名 - iOS/OSX フレームワークの作成: 他の開発者に配布する前にコード署名する必要がありますか?

于 2015-07-07T13:48:50.043 に答える
59

これはそれほど明確な解決策ではありませんが、私が見つける唯一の方法があります:

  1. ONLY_ACTIVE_ARCH=NOで設定Build Settings

    • シミュレーター用のライブラリーをビルドする
    • デバイスのライブラリをビルド
  2. フレームワークのコンソールProductsフォルダーで開きます (フレームワークフォルダーを開いてそこから開くことができますcd ..

ここに画像の説明を入力 ここに画像の説明を入力

  1. このスクリプトをProductsフォルダーから実行します。このフォルダに Fat Framework を作成します。(または、以下の3. 4.で説明するように手動で行います)

または:

  1. このスクリプトでlipoを使用してこれら 2 つのフレームワークを結合YourFrameworkNameします (フレームワーク名に置き換えます)。

    lipo -create -output "YourFrameworkName" "Debug-iphonesimulator/YourFrameworkName.framework/YourFrameworkName" "Debug-iphoneos/YourFrameworkName.framework/YourFrameworkName"
    
  2. 既存のフレームワークの新しいバイナリ 1 に置き換えます。

    cp -R Debug-iphoneos/YourFrameworkName.framework ./YourFrameworkName.framework
    mv YourFrameworkName ./YourFrameworkName.framework/YourFrameworkName
    

  1. 利益: ./YourFrameworkName.framework-すぐに使えるファット バイナリです! プロジェクトにインポートできます!

ワークスペースにないプロジェクトの場合:

ここで説明されているように、この要点を使用することもできます。しかし、ワークスペース内のプロジェクトでは機能しないようです。

于 2015-04-15T12:34:17.673 に答える
10

@Stainlavの回答は非常に役に立ちましたが、代わりにフレームワークの2つのバージョン(デバイス用とシミュレーター用)をコンパイルし、次を追加しRun Script Phaseて、実行中のアーキテクチャに必要なプリコンパイル済みフレームワークを自動的にコピーしました

echo "Copying frameworks for architecture: $CURRENT_ARCH"
if [ "${CURRENT_ARCH}" = "x86_64" ] || [ "${CURRENT_ARCH}" = "i386" ]; then
  cp -af "${SRCROOT}/Frameworks/Simulator/." "${SRCROOT}/Frameworks/Active"
else
  cp -af "${SRCROOT}/Frameworks/Device/." "${SRCROOT}/Frameworks/Active"
fi

この方法では、ファット フレームワークを作成する必要も、App Store に送信するときにlipoRealmが不要なスライスを削除する必要もありません。strip-frameworks.sh

于 2016-04-20T16:16:24.970 に答える
2

基本的にこれについて、私は非常に良い解決策を見つけました。これらの簡単な手順に従うだけです。

  1. ココア タッチ フレームワークを作成します。
  2. ビットコードの有効化をいいえに設定します。
  3. ターゲットを選択し、編集スキームを選択します。[実行] を選択し、[情報] タブから [リリース] を選択します。
  4. 他の設定は必要ありません。
  5. シミュレーターが x86 アーキテクチャーで実行されるように、シミュレーターのフレームワークを構築します。
  6. Project Navigator で Products グループをクリックし、.framework ファイルを見つけます。
  7. それを右クリックし、[ファインダーに表示] をクリックします。コピーして任意のフォルダーに貼り付けます。個人的には「シミュレーター」という名前を好みます。
  8. Generic iOS Device のフレームワークをビルドし、手順 6 ~ 9 に従います。フォルダーの名前を「simulator」ではなく「device」に変更するだけです。
  9. デバイスの .framework ファイルをコピーして、他のディレクトリに貼り付けます。私は両方の直接のスーパーディレクトリを好みます。したがって、ディレクトリ構造は次のようになります。
    • デスクトップ
    • デバイス
      • MyFramework.framework
    • シミュレーター
      • MyFramework.framework
    • MyFramework.framework ターミナルを開いてデスクトップに移動します。次のコマンドの入力を開始します。

リポ -create 'device/MyFramework.framework/MyFramework' 'simulator/MyFramework.framework/MyFramework' -output 'MyFramework.framework/MyFramework'

以上です。ここでは、MyFramework.framework 内にある MyFramework バイナリのシミュレーター バージョンとデバイス バージョンをマージします。シミュレーターやデバイスを含むすべてのアーキテクチャー向けに構築されたユニバーサル フレームワークを取得します。

于 2017-01-31T10:02:01.297 に答える
2

私の回答は以下の点をカバーしています:

  • シミュレータとデバイスの両方で動作するフレームワークを作成する

  • 「ファットな」Cocoa Touch フレームワークをエクスポートする方法 (シミュレーターとデバイスの両方)?

  • アーキテクチャ x86_64 の未定義シンボル

  • ld: アーキテクチャ x86_64 のシンボルが見つかりません

ステップ 1: まず、シミュレーター ターゲットを使用してフレームワークをビルドします。

ステップ 2: シミュレーターのビルド プロセスが成功したら、デバイス ターゲットの選択または汎用 iOS デバイスの選択を使用してフレームワークをビルドします。

ステップ 3: ここでフレームワーク ターゲットを選択し、そのために [ビルド フェーズ] の下で [実行スクリプトの追加] を選択し、以下のスクリプト コードをコピーします)。

ステップ 4: 最後に、もう一度ビルドすると、フレームワークはシミュレーターとデバイスの両方の互換性の準備が整います。万歳!!!!

[注: 最終ステップ 4 の前に、互換性のあるフレームワークの両方を用意する必要があります (シミュレータとデバイス アーキテクチャに互換性があります。そうでない場合は、上記のステップ 1 と 2 を正しく実行してください)。

参照画像を参照してください。

ここに画像の説明を入力

ここに画像の説明を入力

以下のコードをシェル領域に配置します。

#!/bin/sh


UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal


# make sure the output directory exists

mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"


# Step 1. Build Device and Simulator versions

xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build

xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build


# Step 2. Copy the framework structure (from iphoneos build) to the universal folder

cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework" "${UNIVERSAL_OUTPUTFOLDER}/"


# Step 3. Copy Swift modules from iphonesimulator build (if it exists) to the copied framework directory

SIMULATOR_SWIFT_MODULES_DIR="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/."

if [ -d "${SIMULATOR_SWIFT_MODULES_DIR}" ]; then

cp -R "${SIMULATOR_SWIFT_MODULES_DIR}" "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule"

fi


# Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directory

lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}"


# Step 5. Convenience step to copy the framework to the project's directory

cp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}"


# Step 6. Convenience step to open the project's directory in Finder

open "${BUILD_DIR}/${CONFIGURATION}-universal"

于 2017-03-08T11:26:22.073 に答える