如何手动将 .xcframework 添加到 Flutter iOS 插件?

Posted

技术标签:

【中文标题】如何手动将 .xcframework 添加到 Flutter iOS 插件?【英文标题】:How to manually add a .xcframework to a Flutter iOS Plugin? 【发布时间】:2021-11-11 19:27:22 【问题描述】:

我正在尝试创建一个 Flutter 插件以使用本机库。 我尝试使用的这个库存储在一个私有存储库中,可以与 Swift Dependency Manager 一起使用。

这让我很头疼,因为我无法在我的插件中添加私有存储库依赖项(我在 .podspec 文件中找不到这样做的方法),所以我做了什么:

    我已使用 Swift 包管理器将插件添加到示例项目中 手动将MyDependency.xcframework文件夹复制到MyPlugin/ios文件夹 在 podspec 文件中引用它,如下所示:
s.preserve_paths = 'MyDependency.xcframework'
s.xcconfig =  'OTHER_LDFLAGS' => '-framework MyDependency' 
s.vendored_frameworks = 'MyDependency.xcframework'

这样做我可以在插件的源代码中使用 MyDependency。

我目前的问题是:这只适用于模拟器

在此之前,该项目在真实设备上运行没有任何问题。

这是我每次尝试在真实设备上运行时收到的错误消息:

另外,我已经直接从 Swift Dependency Manager 使用依赖项进行了测试,并且工作正常。我认为问题在于我将框架添加到插件的方式。

【问题讨论】:

你在没有.xcframework的iOS物理设备上成功构建应用了吗?此外,您不需要添加所有 3 个步骤(cocoapods、SPM 和 xcframework)。只需将.xcframework 拖入您的项目即可。 是的,没有 .xcframework 它工作正常。我不想将 .xcframework 直接拖到我的项目中。我需要创建一个可以在我们这里拥有的其他项目中使用的插件。另外,我(认为)没有直接访问 .xcframework 的权限。我执行这 3 个步骤只是为了让 SPM 下载的文件。 那么,您希望该封闭源代码的分发策略是什么?我不明白如果 SPM 是封闭源代码,您如何使用它。 第一个屏幕截图发生在您没有正确设置项目/设备时。您的设备需要自动添加到您的配置文件中。我认为您拥有 Apple Developer Program 会员资格并在签名和能力下选择了正确的团队? 第二个屏幕截图(在您的示例项目 Runner 中显示 SPM)只是您的库,它可能/可能没有 .xcframework。此外,当用户将您的插件添加到他们的项目中时,您的插件会通过 cocoapods 而不是 SPM 添加。当你屏蔽名字时,你会让事情变得更难看????。 SPM 不适用于您,恕我直言。 【参考方案1】:

我通过在xxx.podspec 中添加以下几行来开始工作:

s.preserve_paths = 'xxxxxx.xcframework/**/*'
s.xcconfig =  'OTHER_LDFLAGS' => '-framework xxxxxx' 
s.vendored_frameworks = 'xxxxxx.xcframework'

注意s.preserve_paths末尾的/**/*

这是完整的xxx.podspec 文件:

#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
# Run `pod lib lint xxx.podspec` to validate before publishing.
#
Pod::Spec.new do |s|
  s.name             = 'xxx'
  s.version          = '1.0.0'
  s.summary          = 'xxx'
  s.description      = <<-DESC
xxx is a flutter plugin
                       DESC
  s.homepage         = 'https://example.com'
  s.license          =  :file => '../LICENSE', :type => 'BSD' 
  s.author           =  'xxx' => 'email@example.com' 
  s.source           =  :path => '.' 
  s.source_files = 'Classes/**/*'
  s.dependency 'Flutter'
  s.platform = :ios, '10.0'

  # Flutter.framework does not contain a i386 slice.
  s.pod_target_xcconfig =  'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' 
  s.swift_version = '5.0'

  s.preserve_paths = 'xxxxxx.xcframework/**/*'
  s.xcconfig =  'OTHER_LDFLAGS' => '-framework xxxxxx' 
  s.vendored_frameworks = 'xxxxxx.xcframework'
end

确保将xxxxxx.xcframework 目录复制到.../xxx/ios/xxxxxx.xcframework(您的插件xxx.podspec 所在的位置)


xxxxxx.xcframework 添加到Pods 方案以便能够导入它

运行flutter命令创建插件ie时,Frameworks目录应该在Pods方案之下。

flutter create --org com.xxx --template=plugin --platforms=android,ios -a java -i swift xxx

来源:Developing packages & plugins

(如果没有,添加它)

    导航到Pods方案并右键单击Frameworks 点击Add Files to "Pods"...

    导航到ios 目录的根目录,xxxxxx.xcframework 所在的目录 取消选中Copy items if needed 选择Create folder references 检查Pods-Runner 检查您的插件,即。 xxx 点击Add

xxxxxx.xcframework 嵌入到您的项目中

(这应该允许您运行/发布到真实设备)

    点击Pods方案 在TARGETS 中选择Pods-Runner 点击General标签 确保xxxxx.xcframework 出现在Frameworks and Libraries 下方(如果没有,请单击+ 添加) 将Embed 更改为Embed &amp; Sign

    点击你的插件,即。 xxx 确保xxxxx.xcframework 出现在Frameworks and Libraries 下面 将Embed 更改为Embed &amp; Sign

    同样,对于Pods 方案下的两个目标,接下来的步骤应该已经没问题了,但只需检查一下 点击Build Phases 点击Link Binary With Libraries 确保xxxxx.xcframework 存在,如果不存在,请单击+ 并确保Status 设置为Required

现在您应该能够导入框架并在您的代码中引用它,并且应该也可以正常发布。

希望这会有所帮助,祝你好运。我希望这不会很快再次改变

手指交叉

【讨论】:

感谢您发布您的解决方案!我正在阅读并且有疑问,也许您可​​以解释一下...我注意到您手动将框架文件添加到 Pods... 在 Flutter 默认的 .gitignore 文件中,此文件夹被列为未版本控制...这真的适用于其他开发人员还是本地解决方案? @siega 只要您嵌入(第 8 步)xcframework,它就可以工作。【参考方案2】:

在做了一些研究之后,我发现some links 给了我一个关于真正问题的想法......

为了解决这个问题,我在主项目的构建过程中添加了一个简单的脚本。

此脚本将代码签名添加到内部 .framework 文件中。

cd "$CODESIGNING_FOLDER_PATH/Frameworks/"

# flatten nested frameworks by copying to APP.app/Frameworks
for framework in *; do
    if [ -d "$framework" ]; then
        if [ -d "$framework/Frameworks" ]; then
            echo "Moving embedded frameworks from $framework to $PRODUCT_NAME.app/Frameworks"
            cp -R "$framework/Frameworks/" .
            rm -rf "$framework/Frameworks"
        fi
    fi
done

# remove any leftover nested frameworks (i.e. 'PackageName_359AFEED79E48935_PackageProduct.framework')
for framework in *; do
    if [ -d "$framework" ]; then
        if [ -d "$framework/Frameworks" ]; then
            echo "Removing embedded frameworks from $framework to $PRODUCT_NAME.app/Frameworks"
            rm -rf "$framework/Frameworks"
        fi
    fi
done

# codesign for Debugging on device
if [ "$CONFIGURATION" == "Debug" ] & [ "$SDKROOT" != *Simulator* ] ; then

    echo "Code signing frameworks..."
    find "$CODESIGNING_FOLDER_PATH/Frameworks" -maxdepth 1 -name '*.framework' -print0 | while read -d $'\0' framework
    do
        # only sign frameworks without a signature
        if ! codesign -v "$framework"; then
            codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" --preserve-metadata=identifier,entitlements --timestamp=none "$framework"
            echo "Added missing signature to '$framework'"
        fi
    done
fi

【讨论】:

以上是关于如何手动将 .xcframework 添加到 Flutter iOS 插件?的主要内容,如果未能解决你的问题,请参考以下文章

使用来自 xcfamework 的字体

如何使用 SPM 托管在私有仓库中的 .zip 格式的二进制或 xcFramework

C++ FLTK FL_INPUT 检测何时按下输入然后将文本添加到 FL_TEXT_DISPLAY

二进制XCFramework是否可以和旧版swift一起使用?

Angular:如何手动将打字文件添加到打字稿

如何手动将新记录正确添加到空记录集中?