利用Salesforce移动SDK离线使用您的应用程序
您的移动应用程序在没有互联网连接的情况下可以工作吗?请看看使用Salesforce Mobile SDK将离线功能添加到您的应用中是多么容易。
去年,我和我的妻子第一次获得了建造一个全新的家的经验。这个过程很有趣,也很刺激,但我们也经历了经常伴随着新房小区的互联网服务的意外中断。
虽然这些中断影响了我的家人使用流媒体服务的能力,如亚马逊Prime、Hulu和Netflix,但我继续在我目前的项目上工作,由于有意设计能够在隔离(或离线)状态下工作。当我在一年中从内华达和佛罗里达工作时,这在航空旅行中一直很有帮助。
这让我想知道为什么更多的移动应用程序没有被设计成在互联网服务中断时继续工作。
在这份出版物中,我将展示使你的移动应用在离线模式下可用是多么容易。由于我最近使用了Salesforce Mobile SDK,我想继续探索这个移动应用程序的选项。
使用Salesforce Mobile SDK进行离线工作
在我们开始写代码之前,让我们简单地谈谈离线功能如何在Salesforce Mobile SDK中工作。
插图的左侧展示了利用Salesforce应用程序的传统方式。右侧提供了Salesforce Mobile SDK的高级概述。
在Android或iOS设备上运行的本地应用程序可以在Android Studio、Xcode或React Native中编写。这些应用程序包括用户界面、某种程度的业务逻辑,以及代表最终在Salesforce中存在的元素的模型对象。
Salesforce移动SDK包括一个SmartStore方面,当移动应用程序不能访问Salesforce服务时,它可以提供数据。模型层可以很容易地设计成在需要(或喜欢)离线模式时利用SmartStore,但在可以使用在线状态时准备与Salesforce同步所有变化。
如果你想阅读关于这种设计的更多信息,请查看 "使用SmartStore安全地存储离线数据"。
为Finny的食品添加离线能力
今年早些时候,我探索了Salesforce Mobile SDK,并创建了一个名为Finny's Foods的虚构应用。我使用Android、iOS和React Native三次创建了该应用。我想我会从使用Salesforce Mobile SDK的iOS/xCode(Swift)版本的出版物开始,然后在其基础上提供离线功能。
原始文章的GitLab仓库列在下面。
第一步是在userstore.json 文件中建立SmartStore功能所使用的Meal__c 对象。
{
"soups": [
{
"soupName": "Meal__c",
"indexes": [
{ "path": "Id", "type": "string"},
{ "path": "Name", "type": "string"},
{ "path": "Rating__c", "type": "integer"},
{ "path": "__local__", "type": "string"}
]
}
]
}
接下来,更新usersyncs.json 文件,使当前的餐点列表可以离线使用。
JSON
{
"syncs": [
{
"syncName": "syncDownMeals",
"syncType": "syncDown",
"soupName": "Meal__c",
"target": {"type": "soql", "query":"SELECT Id, Name, Rating__c FROM Meal__c ORDER BY Name ASC"},
"options": {"fieldlist":["Id", "Name", "Rating__c", "LastModifiedDate"], "mergeMode":"LEAVE_IF_CHANGED"}
}
]
}
你可以在 "用配置文件注册汤"中阅读关于SmartStore同步配置的所有内容。
随着SmartStore配置的到位,我重构了MealsListModel.swift 类,如下所示。
Swift
class MealsListModel: ObservableObject {
@Published var meals: [Meal] = []
var store: SmartStore?
var syncManager: SyncManager?
private var syncTaskCancellable: AnyCancellable?
private var storeTaskCancellable: AnyCancellable?
init() {
store = SmartStore.shared(withName: SmartStore.defaultStoreName)
syncManager = SyncManager.sharedInstance(store: store!)
}
func fetchMeals(){
syncTaskCancellable = syncManager?.publisher(for: "syncDownMeals")
.receive(on: RunLoop.main)
.sink(receiveCompletion: { _ in }, receiveValue: { _ in
self.loadFromSmartStore()
})
self.loadFromSmartStore()
}
private func loadFromSmartStore() {
storeTaskCancellable = self.store?.publisher(for: "select {Meal__c:Id}, {Meal__c:Name}, {Meal__c:Rating__c} from {Meal__c}")
.receive(on: RunLoop.main)
.tryMap {
$0.map { (row) -> Meal in
let r = row as! [String?]
return Meal(id: r[0] ?? "", Name: r[1] ?? "", Rating__c: (r[2]! as NSString).doubleValue)
}
}
.catch { error -> Just<[Meal]> in
print(error)
return Just([Meal]())
}
.assign(to: \MealsListModel.meals, on:self)
}
}
我更新了fetchMeals() 函数,以便默认与SmartStore互动,在需要时调用Salesforce,但允许在设备处于离线模式时使用存储在应用程序中的数据。
信不信由你,这就是所有的要求。
离线行动中的Finny's Foods
从XCode和iPhone 8模拟器启动Finny's Foods后,我们看到下面的屏幕显示与原始出版物中的一样。
现在,如果我将设备与互联网断开,并重新加载应用程序,XCode中会出现以下日志。
外壳
2022-03-14 16:14:15.544412-0400 FinnysFoodsIOS[88679:6546397] [MobileSync]
CLASS: SFSyncDownTask runSync failed:{ ... } cause:Server call for
sync down failed errorError Domain=NSURLErrorDomain Code=-1009
"The Internet connection appears to be offline."
然而,该应用程序仍然加载并提供来自SmartStore的数据。事实上,如果不看XCode中的日志,我根本不知道我在用本地版本的数据工作。
对于允许添加或更新数据的离线应用程序,SmartStore有能力通过同步管理器合并离线和在线数据。更多信息请参见同步数据文档。
结论
尽管互联网连接不断改善,但可靠的连接并不能100%保证。有远见的功能开发者应该考虑采取适当的措施,让他们的应用程序在互联网连接不可用时继续工作。问问你自己。在断开连接的状态下工作时,我的应用程序如何才能做得更好?
自2021年以来,我一直在努力遵循以下的使命宣言,我觉得它可以适用于任何IT专业人士。
"把你的时间集中在提供特性/功能上,以扩大你的知识产权的价值。充分利用框架、产品和服务来处理其他事情。
- J. Vester
在这篇文章中,我提供了一个例子,说明使用Salesforce Mobile SDK实现离线功能是多么容易。Salesforce工程设计了模型层的集成点,这是确定是否可以检索实时数据或是否应返回SmartStore数据的最佳位置。
显然,Salesforce坚持了我的个人使命感,提供了一个易于采用的设计,而没有大量的模板代码。
如果你对本文的源代码感兴趣,你可以在GitLab上找到它。
祝你有一个非常好的一天!