# \[iOS] Build a Universal Framework for iOS using Swift

## 建立Cocoa Touch Framework

(1.) 打開Xcode, 建立一個Cocoa Touch Framework專案名為testFramework

![](/files/-LI1bjtNb4EbFcneWWew)

打開專案會看到以下結構:

![](/files/-LI1chW9k0APKVip3nV-)

(2.) 將你的程式碼放進testFramework目錄下\
&#x20;      需注意: Cocoa Touch Framework裡面所有的Class都必須是**public**或**open**的封裝

![](/files/-LI1e8klQRv2D3SGNi_X)

(3.)  按下Build按鈕, 你會在Products資料夾下找到你的framework檔案.

&#x20;       此時的framework只能支援simulator 或 device 其中一種, 根據你build的時候所選擇的環境.

&#x20;       如下圖選擇的是simulator  (iPhone X)

![](/files/-LI1d93crxcRJX5cwEnG)

## 建立Universal Framework

(1.) 新增一個target, 選擇**Cross-platform -> Aggregate**

![](/files/-LI1fEImfKQlFtoQqpnR)

名為UniversalFramework

![](/files/-LI1fX0Lp5Tx3RufsRHi)

(2.) 到UniversalFramework Target的**Build Phase,** &#x6309;**+**&#x6309;鈕, 新增一個**Run Script Phase**

![](/files/-LI1gBhJNBRUXLy_q_1q)

(3.) 輸入以下Script

```javascript
#!/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 "${PROJECT_DIR}"
```

![](/files/-LI1gR-0HRBPMVmCAmWH)

(4.) Build UniversalFramework Target, 完成後,  打開framework檔案的目錄

![](/files/-LI1h03870l7gsw0Ep8d)

你會看到有一個universal的資料夾, 裡面的framework檔案即是**simulator & device通用**的Universal Framework .

![](/files/-LI1hBukv1gE8jN1RW6Q)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://frost.gitbook.io/iosbook/ios/ios-book/ios-build-a-universal-framework-for-ios-using-swift.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
