BMLTiOSLib 介于 BMLT Root Server 的语义接口 和您的 iOS 应用之间
这个项目是一个 iOS 共享框架,旨在简化将 BMLT Root Server 集成到 iOS 客户端的过程 (它也可能适用于 MacOS,但我们尚未进行尝试)。BMLTiOSLib 是一个仅限 Swift 的框架,不支持 Objective-C。BMLTiOSLib/Framework 目录包含相关的导出类。BMLTiOSLib/Test Harness Project 目录实现了一个相当复杂的程序,我们编写该程序是为了测试这个库。由于 Apple 现在要求 iOS 应用仅与 SSL 服务器交互,因此测试起来有点复杂。我们不想通过允许连接到自签名证书来损害安全性,因此我们无法使用 localhost 进行测试。
小提示: 我们使用 Charles Proxy 来检查模拟器和服务器之间的交互。可以将 Charles 设置为“中间人”来解密 SSL 交互。
为了便于测试,您可以连接到 BMLT 测试服务器,该服务器使用 SSL。此数据库可能会经常更改,因为它是我们的主要测试平台,但它始终可以通过 SSL 访问。BMLTiOSLib 测试器应用 并不美观,它本就不是为了美观而设计的。它是一个航天飞机驾驶舱程序,旨在让我们能够按下所有各种按钮。它在操作方面也有一些问题,坦率地说,修复这些问题不是当务之急,因为我们现在有几个“真实世界”的实现,它们对 BMLTiOSLib 的压力比这个丑陋的小鸭子要大得多。
您可以使用 Swift Package Manager 包含 BMLTiOSLib,只需引用 它的 GitHub 存储库 URI (SSH: git@github.com:bmlt-enabled/BMLTiOSLib.git 或 HTTPS: https://github.com/bmlt-enabled/BMLTiOSLib.git)。
然后,您需要导入该模块,方法是将以下内容添加到将访问该库的源文件中:
import BMLTiOSLib
要从 Carthage 中使用它,只需将以下内容添加到您的 Cartfile 中:
github "bmlt-enabled/BMLTiOSLib"
然后,cd
到项目目录,并在命令行上执行 carthage update
。
然后,您需要导入该模块,方法是将以下内容添加到将访问该库的源文件中:
import BMLTiOSLib
应该注意的是,Carthage 在 App Store 预配置方面可能会有问题,您可能需要自己构建框架,以避免这些问题。
您还可以直接从其 作为 GitHub 存储库的位置访问此项目,并将其包含到您的项目中。
BMLTiOSLib 使用 BMLT JSON 语义接口 与 Root Server 通信。管理是使用 BMLT 管理语义接口 (也是 JSON) 完成的。整个想法是将通信层从应用开发过程中完全抽象出来。BMLTiOSLib 为 BMLT 提供了一个简单、经过错误检查的功能接口。与 BMLTiOSLib 的交互是通过 Apple 的 委托模式 完成的。当您实例化 BMLTiOSLib 的实例时,您将您的应用注册为 BMLTiOSLibDelegate 委托实例,它将接收传入的事件。然后,您使用功能接口来操作连接。
BMLTiOSLib 类代表 BMLTiOSLib 框架的公共接口。需要使用指向有效 Root Server 的 URI(与用于登录的 URI 相同)和一个 BMLTiOSLibDelegate 委托实例来实例化此类。实例化会立即启动通信过程,结果将反映在委托的 bmltLibInstance(_ inLibInstance: BMLTiOSLib, serverIsValid: Bool) 回调中。如果此实例无法连接到有效的 Root Server,则应将其删除,然后重新实例化以建立新连接。建立连接后,HTTP 会话将保持,直到该实例被取消实例化。语义管理需要保持会话。您不能在 BMLTiOSLib 的多个实例之间共享会话。
成功连接(建立会话)到 Root Server 后,此实例将提供有关该服务器的一些基本信息。当连接成功时 (serverIsValid
为 true),将调用您的委托的 bmltLibInstance(_ inLibInstance: BMLTiOSLib, serverIsValid: Bool) 方法。可以通过调用以下 BMLTiOSLib 实例属性来访问此信息:
distanceUnits 和 distanceUnitsString (这是服务器使用的距离单位 - Km 或 Mi)。
availableMeetingValueKeys (这包含可访问各种会议属性的字典键字符串)。
emailMeetingContactsEnabled (如果服务器设置为允许向会议联系人发送电子邮件,则为 True)。
emailServiceBodyAdminsEnabled (如果这些电子邮件将抄送给该服务主体的服务主体管理员以及会议联系人 - 它们可能是相同的电子邮件地址,则为 True)。
changeDepth (每个会议保存的更改次数)。
googleAPIKey (Root Server 的 Google Maps API 密钥 - 可能对大多数其他服务器无用)。
delegate (这将是对象 - 实现 BMLTiOSLibDelegate 协议的对象,该对象在 创建实例时作为委托传递)。
versionAsString 和 versionAsInt (服务器版本)
isAdminAvailable (如果语义管理可用,则为 True)。
defaultLocation (Root Server 的默认中心位置)。
serviceBodies (这是一个“扁平”的服务主体数组,没有层次结构)。
hierarchicalServiceBodies (这将在它们在 Root Server 上占据的层次结构中映射服务主体,这只是一个只有子节点的节点 - 没有父节点或服务主体)。
allPossibleFormats (可用的格式对象的数组 - 可能并非所有对象都由会议使用)。
availableServerLanguages (语言对象的数组)。
您可以通过检查必需的 bmltLibInstance(_ inLibInstance: BMLTiOSLib, serverIsValid: Bool) 调用中的 serverIsValid
参数的值来确定连接是否成功
public func bmltLibInstance(_ inLibInstance: BMLTiOSLib, serverIsValid: Bool) {
if serverIsValid {
•
•
•
•
}
}
如果发生任何错误,则会进行必需的 bmltLibInstance(_ : BMLTiOSLib, errorOccurred: Error) 调用
public func bmltLibInstance(_ inLibInstance: BMLTiOSLib, errorOccurred: Error) {
•
•
•
•
}
这是一张简短的图片,显示了 BMLTiOSLib 在建立连接时的行为
使用此类进行会议搜索的方法是获取该实例的 searchCriteria 对象,并使用其各种属性来设置所需的搜索。完成后,调用此类实例的 performMeetingSearch(_:BMLTiOSLibSearchCriteria.SearchCriteriaExtent) 方法,指示您是只想要会议,还是只想要搜索结果中的会议使用的格式,还是两者都想要。搜索完成后,此类将调用您的委托例程
bmltLibInstance(_:BMLTiOSLib,meetingSearchResults:[BMLTiOSLibMeetingNode]) 被调用,并带有会议搜索的结果。
bmltLibInstance(_:BMLTiOSLib,formatSearchResults:[BMLTiOSLibFormatNode],isAllUsedFormats:Bool) 被调用,并带有格式搜索的结果。
根据您调用 performMeetingSearch(_:BMLTiOSLibSearchCriteria.SearchCriteriaExtent) 时请求的内容,可能会调用其中一个或两个。 如果没有结果,它们将被调用并返回空数组。 您可以获取会议搜索结果、给定会议搜索所使用的格式,或者两者都获取。 这些结果将在以下两个 BMLTiOSLibDelegate 调用中返回。
public func bmltLibInstance(_ inLibInstance: BMLTiOSLib, meetingSearchResults: [BMLTiOSLibMeetingNode]) {
•
•
•
•
}
public func bmltLibInstance(_ inLibInstance: BMLTiOSLib, formatSearchResults: [BMLTiOSLibFormatNode], isAllUsedFormats: Bool) {
•
•
•
•
}
如果 isAllUsedFormats 为 false,则返回的格式**仅**为搜索中指定的会议集合中使用的格式。 如果 isAllUsedFormats
为 true,则格式集为服务器上的每个可用格式;无论该格式是否被任何会议使用(基本上与 allPossibleFormats 实例属性的内容相同)。
您可以查询会议变更,包括已删除的会议 (如果您是授权的管理员,您可以恢复已删除的会议)。 您可以通过调用以下方法之一来执行此操作:
getAllMeetingChanges(fromDate:Date?,toDate:Date?,meetingID:Int?)
getAllMeetingChanges(fromDate:Date?,toDate:Date?,serviceBodyID:Int?)
getAllMeetingChanges(fromDate:Date?,toDate:Date?,serviceBodyID:Int?,meetingID:Int?)
getAllMeetingChanges(fromDate:Date?,toDate:Date?,serviceBodyID:Int?,meetingID:Int?,userID:Int?)
getDeletedMeetingChanges(fromDate:Date?,toDate:Date?,serviceBodyID:Int?)
getDeletedMeetingChanges(fromDate:Date?,toDate:Date?,serviceBodyIDs:[Int]?)
调用上述方法之一后,您的代理将被调用并返回 bmltLibInstance(_:BMLTiOSLib,changeListResults:[BMLTiOSLibChangeNode]) 方法;该方法将包含请求的变更对象的数组。 然后,您可以使用这些对象来恢复会议或还原已删除的会议。
public func bmltLibInstance(_ inLibInstance: BMLTiOSLib, changeListResults: [BMLTiOSLibChangeNode]) {
•
•
•
•
}
在某些根服务器中,管理员可以选择启用站点用户向指定会议联系人(或负责会议的服务机构管理员)发送消息的功能。 在这些情况下,消息以电子邮件形式接收,但发送者不发送电子邮件。 相反,他们使用 BMLTiOSLibMeetingNode 类的一种方法,称为 sendMessageToMeetingContact(fromAddress:String,messageBody:String)。 消息在后台发送。 发送消息后,将使用 bmltLibInstance(_:BMLTiOSLib,sendMessageSuccessful:Bool) 方法调用您的代理。
为了在根服务器上执行管理,您需要使用 adminLogin(loginID:String,password:String) 方法登录。 登录将在该对象(及其连接会话)的生命周期内保持有效,或者直到调用 adminLogout() 方法为止。 会议搜索的结果可能会将会议对象作为 BMLTiOSLibEditableMeetingNode 的实例而不是 BMLTiOSLibMeetingNode 的实例返回(只要您以管理员身份登录,并且有足够的权限来编辑会议)。 这将取决于登录对给定会议的编辑权限。 如果您无法编辑会议,则该实例将是 BMLTiOSLibMeetingNode 的实例,而不是 BMLTiOSLibEditableMeetingNode 的实例。 如果该实例是 BMLTiOSLibEditableMeetingNode,则 isEditable 属性将返回 true。 如果该实例是 BMLTiOSLibEditableMeetingNode 类,则可以将其强制转换为该类,并操作公共属性。 设置属性后,您可以调用该实例的 saveChanges() 方法,然后将保存该会议。 在调用 saveChanges() 方法之前,不会将会议更改发送到服务器。 保存会议后,您的代理将收到对其 bmltLibInstance(_:BMLTiOSLib,adminMeetingChangeComplete:BMLTiOSLibChangedMeeting!) 方法的调用,该方法将包含会议更改的任何字段,以及“before”和“after”值(始终为字符串)。 您还可以通过调用 delete() 方法来删除会议(删除立即发生)。 如果您删除会议,则将使用 bmltLibInstance(_:BMLTiOSLib,deleteMeetingSuccessful:Bool) 方法调用您的代理。 如果您调用 restoreToOriginal() 方法,则对会议对象所做的任何更改都将恢复为服务器上会议的状态。 不会向服务器发送任何内容。 您还可以使用 revertMeetingToBeforeThisChange(_:BMLTiOSLibChangeNode) 方法将会议恢复为在该会议的给定更改记录之前的状态。 不会向服务器发送任何内容。 如果该更改不适合该会议,则调用将返回 false。 如果成功,会议的状态将恢复为更改记录中的状态,但尚未发送到服务器。 您仍然需要调用 saveChanges()。
选择变更的 saveMeetingToBeforeThisChange() 或可编辑的会议对象 将使用语义管理界面的恢复删除或回滚功能(只要您以管理员身份登录,并且有足够的权限来编辑会议)。 我们确实允许您获取会议的“before”记录(在 json_data
JSON 响应或更改记录对象的 beforeObject 属性中找到),并保存它。 这允许您添加新的更改(而不是简单地接受回滚中的整个更改,您可以选择仅进行某些更改)。 它还在会议历史记录中提供更好的变更记录。 现在,您有一个精确的字段更改列表,而不是简短的“会议已回滚到以前的版本”。 请记住,beforeObject 和 afterObject 属性是完全限定的会议对象,如果可编辑,则可以保存,这将覆盖数据库中当前存在的任何内容(这与保存更改的会议记录完全一样)。 您可以通过调用相关更改记录对象的 revertMeetingToBeforeThisChange() 方法来恢复会议。 这非常简单。
创建新会议很容易(只要您以管理员身份登录,并且有足够的权限来创建会议)。 您创建一个 ID 为 0(默认值)的 BMLTiOSLibEditableMeetingNode 实例。 然后,当您调用 saveChanges() 时,它将创建一个新会议。 当您创建新会议或恢复已删除的会议时,将使用 bmltLibInstance(_:BMLTiOSLib,newMeetingAdded:BMLTiOSLibEditableMeetingNode) 方法调用您的代理。 newMeetingAdded
参数将包含一个对新建的会议进行建模的对象(包括新的 ID,如果是全新的会议)。
使任务可中断,而无需终止会话。 目前,终止任务的方法是终止会话。 这对于搜索应用程序非常有效,但对于管理应用程序不太好,因为会话带有登录信息。 如果您终止会话,您会强制用户重新登录。
使库支持多任务处理。 目前,该库以单线程方式工作。 它应该能够处理多个并发任务。
针对简单的 TVOS Swift 应用程序进行测试
针对简单的 MacOS Swift 应用程序进行测试