绑定 Xamarin.iOS 中的 Swift 库
绑定 Xamarin.iOS 中的 Swift 库遵循与 Objective-C 相同的过程,如 https://developer.xamarin.com/guides/ios/advanced_topics/binding_objective-c/ 所示,但有一些注意事项。
- swift 类必须从 NSObject 继承才能绑定。
- 除非在 swift 类中使用 @objc 注释(例如 @
objc(MyClass)
)来指定显式目标 c 名称,否则 Swift 编译器会将类和协议名称转换为其他名称。 - 在运行时,你的 APP 必须在名为 Frameworks 的文件夹中包含一些快速核心库以及绑定框架;
- 当应用程序被推送到 AppStore 时,它必须在你的 Payload 文件夹旁边包含一个 SwiftSupport 文件夹。这些都在 IPA 文件中。
在这里你可以找到一个简单的样本绑定: https : //github.com/Flash3001/Xamarin.BindingSwiftLibrarySample
以及完整的绑定示例: https : //github.com/Flash3001/iOSCharts.Xamarin
请找到以下步骤:
1.1 准备要导出的 Swift 类
对于你要使用的任何 Swift 类,你必须从 NSObject 继承并使用 objc 注释显式显示 Objective-C 名称。否则 Swift 编译器将生成不同的名称。下面是 Swift 类的外观示例代码。请注意,只要根类继承自 NSObject,它继承哪个类并不重要。
//Add this to specify explicit objective c name
@objc(MyClass)
open class MyClass: NSObject {
open func getValue() -> String
{
return "Value came from MyClass.swift!";
}
}
1.2 构建框架
禁用 Bitcode。 *
构建适用于设备和模拟器的版本。 *
- 与 Swift 绑定无关。
2.创建一个胖库
一个框架包含几个文件,需要吃一点的是 NAME.framework / NAME(没有扩展名)。
- 将 Release-iphoneos / NAME.framework 复制到 NAME.framework
- 使用以下命令创建 FAT 库:
- lipo -create Release-iphonesimulator / NAME.framework / NAME Release-iphoneos / NAME.framework / NAME -output NAME.framework / NAME
- 将 Release-iphonesimulator / NAME.framework / Modules / NAME.swiftmodule 中的文件复制到 NAME.framework / Modules / NAME.swiftmodule(直到现在它只包含来自 iphoneos 的文件)
3.导入库
我假设你已经在 File - > New - > iOS - > Binding Library 中创建了 Binding 项目。
Xamarin 支持导入 .frameworks。只需右键单击 Native References
,然后单击 Add native reference
。找到新创建的胖框架并添加它。
4.根据头文件中的 LIBRARY-Swift.h 文件创建 ApiDefinition
你可以手动完成它,但它不会很好。你可以使用 Objetive Sharpie。Xamarin 工具用于绑定自己的库。
如何在 https://developer.xamarin.com/guides/cross-platform/macios/binding/objective-sharpie/ 上使用它
基本命令将类似于: sharpie bind -sdk iphoneos9.3 NAME-Swift.h
如果你得到了 System.Reflection.TargetInvocationException
,可能是因为你安装了不同的 SDK 版本。运行以下命令以检查已安装的 iPhone OS SDK:
sharpie xcode -sdks
NAME-Swift.h 文件位于 NAME.framework / Headers / NAME-Swift.h 中
注意:swift 类必须继承自 NSObject
,否则 NAME-Swift.h 将不会导入你的类,而 Objetive Sharpie 将不会转换任何内容。
用新创建的项目替换绑定项目 ApiDefinition.cs 的内容。
5.更改所有[Protocol]和[BaseType]以在 Objective-C 运行时中包含类的名称
如果原始 Swift 类或协议不包含步骤 1.1 中指定的 @objc(MyClass)
注释,则它们的内部 Objective-C 名称将更改,因此你需要将其映射到正确的名称。
所有名称都以 NAME-Swift.h 文件的形式提供,格式如下:
SWIFT_CLASS("_TtC11SwiftSample7MyClass")
@interface MyClass : NSObject
和
SWIFT_PROTOCOL("_TtP6Charts17ChartDataProvider_")
@protocol ChartDataProvider
要设置名称,请使用 BaseTypeAttribute.Name https://developer.xamarin.com/guides/cross-platform/macios/binding/binding-types-reference/#BaseType.Name 属性以及类和 ProcotolAttribute.Name https:// developer.xamarin.com/api/property/MonoTouch.Foundation.ProtocolAttribute.Name/ 用于协议。
[BaseType(typeof(NSObject), Name = "_TtC11SwiftSample7MyClass")]
interface MyClass
手动完成并不酷。你可以使用此工具 https://github.com/Flash3001/SwiftClassify 插入所有名称。 (它正在进行中。但它非常简单,只需查看代码就可以了解它的工作原理)。
6.1 包括要运行的所有 Swift 依赖项
如果你尝试在应用程序中使用该库并尝试立即运行它将崩溃。错误是由于缺少 libswiftCore.dylib
像这样的东西:
Dyld Error Message:
Library not loaded: @rpath/libswiftCore.dylib
Referenced from: /Users/USER/Library/Developer/CoreSimulator/Devices/AC440891-C819-4050-8CAB-CE15AB4B3830/data/Containers/Bundle/Application/27D2EC87-5042-4FA7-9B80-A24A8971FB48/SampleUsing.app/Frameworks/SwiftSample.framework/SwiftSample
Reason: image not found
Xamarin.iOS 没有为绑定 Swift 库提供官方支持。因此,你必须在 Frameworks 和 SwiftSupport 文件夹中手动包含 swift 核心库。Frameworks 文件夹的文件对于 Simulator 和 Device 是不同的。它们可以在/Applications/Xcode.app/Contents/Developer//XcodeDefault.xctoolchain/usr/lib/swift.Toolchains 中找到
你可以使用此库 https://github.com/Flash3001/Xamarin.Swift3.Support 而不是手动复制 Framework 文件夹中的文件。它包括 Swift 3.1 所需的每个依赖项,每个依赖项都在一个 NuGet 包中。
如你所见,Nuget Package 包含在消费者 App 中,而不是绑定本身。如果你尝试将其包含在绑定中,则会出现编译错误。
如果你正在构建 Nuget 包,则可以指示 Nuget 将其作为依赖项包含在内。
6.2。找出要包含的 Swift 依赖项
一件重要的事情是弄清楚你需要包含在项目中的每个包。通常需要一个简单的绑定:
libswiftCore.dylib
libswiftCoreGraphics.dylib
libswiftCoreImage.dylib
libswiftDarwin.dylib
libswiftDispatch.dylib
libswiftFoundation.dylib
libswiftObjectiveC.dylib
libswiftQuartzCore.dylib
libswiftUIKit.dylib
要列出每个依赖项,可以在 LibraryName.framework 中运行以下命令
otool -l -arch armv7 LibraryName | grep libswift
不要在 NuGet for Swift3 中包含所有可用的包,因为它们可能会增加你的应用程序大小。
7.包括 SwiftSupport 以将 App 推送到 AppStore
Apple 要求你的应用程序与你的 Payload 文件夹一起发送 SwiftSupport 文件夹。两者都在你的 IPA 包中。
你可以使用此脚本 https://github.com/bq/ipa-packager 为你完成此项工作。
此过程是库消费者必须手动执行的唯一过程。每次他/她试图将 App 推送到 AppStore。
单击签名并分发并保存到磁盘
解压缩 .IPA
使用前面提到的脚本创建新的 IPA
如果解压缩文件,它将包含 SwiftSupport 文件夹。
备注
在 Xcode 中构建库时,它可以选择包含 swift 库。别! 它们将作为 NAME.app/Frameworks/LIBRARY.framework/Frameworks/libswift*.dylib 包含在你的最终应用中,但它们必须包含在 NAME.app/Frameworks/libswift*.dylib 中
你可以在其他地方找到此信息,但值得一提的是:不要在库中包含 Bitcode。截至目前,Xamarin 不包括 iOS 的 Bitcode,Apple 要求所有库都支持相同的架构。
放弃
本指南最初由 Lucas Teixeira 创建。所有学分属于他。谢谢你,卢卡斯。