iOS Salesforce SDK 小知识
Salesforce SDK 能做许多任务,因此也比较繁杂,又分了原生,js等多个调用方法。
关键点总结:
- SFSmartStore 中的 - (id) initWithName:(NSString*)name user:(SFUserAccount *)user isGlobal:(BOOL)isGlobal 函数,是关键入口点函数。
- SFSmartStore 中默认把FMDB 和 SQLChiper都引入了,因此FMDB可以调用自身的setKey函数对数据库进行加密操作(不引入SQLChiper库,FMDB就无法使用这个函数)。如果不使用SFSmartStore的类方法+ (void)setEncryptionKeyBlock:(SFSmartStoreEncryptionKeyBlock)newEncryptionKeyBlock;对_encryptionKeyBlock(返回一个加密用的key)进行指定,SFSmartStore就会使用com.salesforce.smartstore.encryption.keyLabel 作为默认的key。如果不需要使用加密功能,只需要把_encryptionKeyBlock的返回值设置为空字符串(oc里就是@"")。
- SFSmartStore 其实就是对FMDB的一层封装!
- SFSmartStore 里的 Soup就是 表 的意思,一般的使用方法如下:
navigator.smartstore.registerSoup("myAgents",
[{path:'name', type:'string'},
{path:'address', type:'string'}]);
navigator.smartstore.upsertSoupEntries("myAgents",
[{name:'James Bond',
address:'1 market st',
agentNumber:"007"}]);
先使用registerSoup注册一个soup,第一个参数指定了soup的名字,第二个参数指定了需要被index 的列(不是主键的意思,该列的内容可以重复)就是所谓的indexSpecs,不被index的列无法把该列作为关键字进行查询,排序等操作。
之后使用upsertSoupEntries向soup插入或更新具体数据,第一个参数还是soup名,第二个参数是具体的数据条目数组,就是所谓的entries数组。理论上说,Entry中的属性和indexSpecs并没有什么包含关系,但是在真实环境里,indexSpecs应该是Entry属性集的一个子集。 再看看查询方法,SFSmartStore 提供了好多的查询方法应对不同需求,比如下面这个:
var querySpec; if (query === "") {
querySpec = smartstore.buildAllQuerySpec("LastName", "ascending", 100);
}
else {
var queryParts = query.split(/ /);
var queryFirst = queryParts.length == 2 ? queryParts[0] : query;
var queryLast = queryParts.length == 2 ? queryParts[1] : query;
var queryOp = queryParts.length == 2 ? "AND" : "OR";
var match = "{contacts:FirstName}:" + queryFirst + "* " + queryOp + " {contacts:LastName}:" + queryLast + "*";
querySpec = smartstore.buildMatchQuerySpec(null, match, "ascending", 100, "LastName");
}
var that = this; lastStoreQuerySent++;
var currentStoreQuery = lastStoreQuerySent; smartstore.querySoup(false,
"contacts",
querySpec,
(cursor) => {
console.log("Response for #" + currentStoreQuery);
if (currentStoreQuery > lastStoreResponseReceived) {
lastStoreResponseReceived = currentStoreQuery;
var contacts = cursor.currentPageOrderedEntries; successCallback(contacts, currentStoreQuery);
}
else {
console.log("IGNORING Response for #" + currentStoreQuery);
}
},
(error) => {
console.log("Error->" + JSON.stringify(error));
errorCallback(error);
});
总结一下就是先构建查询用的字符串,再利用build方法创建出querySpec对象,最后利用相应的query方法查询,结果就是一个数组,数组里的每个元素就是需要的数据对象。
另外还有一种特别的查询,叫 smart query
querySpec = smartstore.buildSmartQuerySpec("select {Person:_soup} from {Person}", 100); smartstore.runSmartQuery(false, querySpec, (cursor)=> { var persons = cursor.currentPageOrderedEntries; var person = persons[0]; }, (error)=> {
});
这里的_soup是固定的,必须这样写。
这个查询结果也是一个数组,但是数组下还是数组,在第二层数组里才是数据对象。截图如下:
这个问题也是困扰了我很久,不太明白其中的意义。
下面是这些问题的官方文档,其实,文档说的也不是很明白。。。
https://developer.salesforce.com/docs/atlas.en-us.mobile_sdk.meta/mobile_sdk/offline_query.htm
再简单说下smartsync的用法,smartsync使用时的关键参数有2个,一个是从服务器抓取数据的sql语句,第二个是要存到本地的soup名字。看一段demo
function syncDown(callback) {
if (syncInFlight) {
console.log("Not starting syncDown - sync already in fligtht");
return;
} console.log("Starting syncDown");
syncInFlight = true;
var fieldlist = ["Id", "FirstName", "LastName", "Title", "Email", "MobilePhone", "Department", "HomePhone", "LastModifiedDate"];
var target = {type: "soql", query: "SELECT " + fieldlist.join(",") + " FROM Contact LIMIT 10000"};
smartsync.syncDown(false,
target,
"contacts",
{mergeMode: smartsync.MERGE_MODE.OVERWRITE},
(sync) => {
syncInFlight = false;
syncDownId = sync._soupEntryId;
console.log("sync==>" + sync);
emitSmartStoreChanged();
if (callback) callback(sync);
},
(error) => {
syncInFlight = false;
}
); }
再来看一下SmartStore不使用加密时,数据库的结构:首先是name表,这里的name就是soup的name,也就是所谓的表名,通过他们对应的id,就可以找到对应的数据表,比如id=1,那么TABLE_1就是它对应的数据表。
再看一下:
这里的index表就是索引表,也就是能够被当做条件进行查询和排序的列的名字,所有的soup的的index都放在一张表里。
下载了SalesforceMobileSDK-iOS-master之后,里面有一个叫做SmartSyncExplorer的 Demo工程,这个工程里有一套salesforce推荐的同步方法,其中比较重要的是如图的几个类。
这几个类是SmartStore和SmartSync的具体利用实例,通过这种结构能够更有条理,更方便地使用这2个库。
具体的分析如下:
这里经常被使用的类是SObjectDataManager,它提供了以下主要方法:
refreshLocalData:从本地数据库读取新数据
refreshRemoteData:从salesforce上的数据库读取新数据到本地数据库,并读取数据
updateRemoteData:从本地数据库上传数据到salesforce数据库
这几个方法在使用时,就需要其他几个类的配合,比如
SObjectData:是soup数据库和oc的接口类,用oc类的方式表示了soup中的数据。其中,soupDict属性就是把SObject中的所有属性和值格式化为一个字典,之后保存这个字典到相应表的soup列里,成为真正保存数据的地方。注意,这里面的property的get和set方法,都被重写了,没有利用每个属性所对应的存储空间,统一使用soupDict中的值。
SObjectDataSpec:是SObjectData中的关键属性,描述了这个SObjectData所需要的主要信息,主要信息如下:
self.objectType //salesforce中对应的object名字 self.objectFieldSpecs //soup表对应的数据结构数组,里面是SObjectDataFieldSpec类型
self.updateObjectFieldSpecs //上传数据到服务器时,需要上传的字段数组,,里面是SObjectDataFieldSpec类型
self.indexSpecs //索引数组,里面是SFSoupIndex类型
self.soupName //本地数据库soup表名
self.orderByFieldName //排序字段名
iOS Salesforce SDK 小知识的更多相关文章
- iOS APP开发的小知识(分享)
亿合科技小编发现从2007年第一款智能手机横空出世,由此开启了人们的移动智能时代.我们从一开始对APP的陌生,到现在的爱不释手,可见APP开发的出现对我们的生活改变有多巨大.而iOS AP ...
- xcode 发展史 及 做iOS 必须知道的小知识
Xcode 3.0 是开发人员建立 Mac OS X 应用程序的最快捷方式,也是利用新的苹果电脑公司技术的最简单的途径.Xcode 3.0 将Mac OS X的轻松使用,UNIX 能量以及高性能的开发 ...
- salesforce 零基础开发入门学习(十)IDE便捷小知识
在这里介绍两个IDE的便捷开发的小知识. 一) 本地调试 由于salesforce代码只能提交以后才能调试,所以很多时候调试代码很麻烦.新版增加了一个特性:即可以在本地调试相关的代码或者查看相关代码运 ...
- 开发者所需要知道的 iOS 10 SDK 新特性
转自:https://onevcat.com/2016/06/ios-10-sdk/ 写的很好啊.哈哈哈 总览 距离 iPhone 横空出世已经过去了 9 个年头,iOS 的版本号也跨入了两位数.在我 ...
- iOS网络相关零散知识总结
iOS网络相关零散知识总结 1. URL和HTTP知识 (1) URL的全称是Uniform Resource Locator(统一资源定位符). URL的基本格式 = 协议://主机地址/路径 ...
- 记录一下学习Android的小知识
目前要设计即时通讯的整体架构,包括服务端.Android.IOS.PC.平板等等系统,所以需要研究一下手机的实现方式,开始从Android入手,偶尔在这记录下小知识. ADT: 1.页面功能请求结构, ...
- fir.im Weekly - 从 iOS 10 SDK 新特性说起
从 iOS 7 翻天覆地的全新设计,iOS 8 中 Size Classes 的出现,应用扩展,以及 Cloud Kit 的加入,iOS 9 的分屏多任务特性,今年的 WWDC iOS 10 SDK ...
- cocos2d-x + Lua接入iOS原生SDK的实现方案[转]
相信很多朋友在使用cocos2d-x+lua开发游戏时都遇到过接入iOS原生SDK的问题,比如常见的接应用内支付SDK,广告SDK或是一些社交平台SDK等等,我也没少接过这类SDK.这篇文章主要是对我 ...
- [原创]cocos2d-x + Lua接入iOS原生SDK的实现方案
相信很多朋友在使用cocos2d-x+lua开发游戏时都遇到过接入iOS原生SDK的问题,比如常见的接应用内支付SDK,广告SDK或是一些社交平台SDK等等,我也没少接过这类SDK.这篇文章主要是对我 ...
随机推荐
- #define与typedef在重定义类型中的区别
#define 为完全的替换 typedef 重新定一个数据类型 eg #define charp1 char* typedef char* charp2charp1 a,b; //a char* b ...
- javascript创建多行字符串的方法(转)
JS里并没有标准的多行字符串的表示方法,但是在用模板的时候,为了保证模板的可阅读性,我们又不可避免的使用多行字符串,所以出现了各种搞法,这里以一段jade的模板作为示例,简单总结和对比一下. 一.字符 ...
- 使用Navicat在oracle XE上新建表空间、用户及权限赋予
参考资料: 烂泥:使用Navicat for Oracle新建表空间.用户及权限赋予 - 烂泥行天下 - 51CTO技术博客http://ilanni.blog.51cto.com/526870/12 ...
- supervisor的使用:
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Helvetica Neue"; color: #e4af0a } sp ...
- 通过WebStorm上传代码至github
首先需要注册github帐号,具体方法自行百度/谷歌. 打开WebStorm,我用的是2016.2.4版本(如果你有edu邮箱的话,可以免费使用一年,不只是Webstorm,JetBrains全家桶都 ...
- javaweb 基于java Servlet登入 简单入门案例
项目流程 第一步:创建一个java webproject第二步:创建三个界面,1,login.jsp 2 success.jsp 3 fail.jsp第三步:更改新建界面编码格式,utf-8 默然编码 ...
- PHP进程通信基础——shmop 、sem系列函数使用
PHP进程通信基础--shmop .sem系列函数使用 进程通信的原理就是在系统中开辟出一个共享区域,不管是管道也好,还是共享内存,都是这个原理.如果心中有了这个概念,就会很方便去理解代码.由于官网上 ...
- Django基础,Day6 - 单元测试tests
在django项目app目录下,有个tests.py,我们通常可以直接在这文件中写我们的单元测试代码. test for a model 根据前面章节的操作步骤下来,在Question Model中有 ...
- 堆排序分析及php实现
堆排序:是一种特殊形式的选择排序,他是简单选择排序的一种改进. 什么是堆? 具有n个元素的序列:{k1,k2,ki,…,kn} (ki <= k2i,ki <= k2i+1) 或者 (ki ...
- 关于TableView上有一段留白的解决方法
当cell的类型是plaint类型时 直接设置self.automaticallyAdjustsScrollViewInsets=NO; 还有要注意检查你自己设置的frame是否正确 当cel ...