Building a Universal Framework in iOS
By: Yuvraj Kale
Tags: Objective C, iOS App Development, Swift Programming, Universal Framework

Photo by Kevin Ku on Unsplash

I have created one Framework that actually provides inbuilt methods to detect the liveness of a person. Framework is created successfully but when that framework is integrated with my app and trying to run on device it was running successfully but whenever I am trying to test it simulator I failed to run it which gives me the following error.

your framework path building for iOS-x86_64 but attempting to link with file built for iOS Device-arm64

I tried every solution for that, like adding all architectures in Build architecture only but it failed then I understand that we have to create a Universal framework that actually supports both simulator and device. For creating a Universal framework I have followed some step that I am trying to explain here so that developer who is facing the same issue can solve that in less time.

As we know the problem statement where we are not able to run app for the simulator or for device after integrating a framework. Following is the warning or error you can see while running an application for a simulator/device.

your framework path building for iOS-arm64 but attempting to link with file built for iOS Simulator-x86_64

The above warning indicates that framework integrated is available for simulator and we are trying to run it on a real device.

your framework path building for iOS-x86_64 but attempting to link with file built for iOS Device-arm64

The above warning indicates that framework integrated is available for a real-device and we are trying to run it on the simulator.

So now we have to create a Universal framework which supports both simulator and real-devices.

Before going into actual problem solving I will give you an idea of what is the build architectures and what they do.

arm6: iPhone 1, 2, 3G

arm7: Used in the oldest iOS 7-supporting devices[32 bit]. iPhone 4, 4s

arm7s: As used in iPhone 5 and 5C[32 bit]. iPhone 5, 5c

arm64: For the 64-bit ARM processor in iPhone 5S[64 bit]. iPhone 5s and above.

arm64e: used on the A12 chipset. iPhone XS/XS Max/XR

i386: For the 32-bit simulator

x86_64: Used in 64-bit simulator

Now the actual problem-solving.

Prerequisite: Create a new folder where you are pasting the framework created. Let’s say the name of the folder is Universal which is located in Desktop.

Creating a framework for Simulator

Change scheme to your Yourframework.framework. Select Any iPhone to let’s say iPhone8. Hit the play button(try to run your application). Now go to the product folder in the Xcode folder list. Here you can see Yourframework.framework, right-click on it and click show in finder. You can see your framework. Copy that framework and past it into the Universal folder we created. Rename that framework as yourframeworkSim.framewrok.

Creating a framework for real-device

Change scheme to your Yourframework.framework. Select Generic iOS Device. Hit the play button(try to run your application). Now go to the product folder in the Xcode folder list. Here you can see Yourframework.framework, right-click on it and click show in finder. You can see your framework. Copy that framework and past it into the Universal folder we created. Rename that framework as yourframeworkDevice.framewrok.

Until now we have a Universal folder located in Desktop which holding two frameworks named yourframeworkDevice.framewrok and yourframeworkSim.framewrok.

The following are the two ways to get the universal framework.

1)Use of COMMAND LINE TOOL

Now you have to open the terminal. From command-line tool goto folder, you created on desktop i.e Universal folder

cd path_to_Universal_folder

Now next and final step we have to hit final command on the command-line tool which created the framework supports to Simulator and device.

lipo -create -output yourframework.framework yourframeworkDevice.framework/yourframeworkDevice yourframeworkSim.framework/yourframeworkSim

lipo -create -output — it helps to create universal binary.

yourframework.framework — This is our final framework name which supports both simulator and a real-time device.

yourframeworkDevice.framework/yourframework — This is a framework which only support for a real-device.

yourframeworkSim.framework/yourframework — This is a framework which only support for a Simulator.

2) You can use either command-line tool or you can add this script by following way

Select Project Target → Edit Schema → Archive → Post-actions → Press “+” → New Run Script Action.

UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-Universal # Make sure the output directory exists

mkdir -p "${UNIVERSAL_OUTPUTFOLDER}" # Next, work out if we're in SIMULATOR or REAL DEVICE

xcodebuild -target "${PROJECT_NAME}" -configuration ${CONFIGURATION} -sdk iphonesimulator ONLY_ACTIVE_ARCH=NO BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean buildxcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build # Step 2. Copy the framework structure (from iphoneos build) to the universal foldercp -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

BUILD_PRODUCTS="${SYMROOT}/../../../../Products"cp -R "${BUILD_PRODUCTS}/Debug-iphonesimulator/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule/." "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/Modules/${PROJECT_NAME}.swiftmodule" # Step 4. Create universal binary file using lipo and place the combined executable in the copied framework directorylipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_PRODUCTS}/Debug-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 directorycp -R "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework" "${PROJECT_DIR}" # Step 6. Convenience step to open the project's directory in Finder

open "${PROJECT_DIR}"

fi

After adding this script you have to archive your framework. And because of this script, your framework folder will automatically get open and you can found the framework and ready to use.

Conclusion

Now finally we have a Universal framework that runs on a simulator and real-time devices. This is one way to create that there is another way for doing that we will see it later on.