zoukankan      html  css  js  c++  java
  • iOS Salesforce SDK 小知识

     Salesforce SDK 能做许多任务,因此也比较繁杂,又分了原生,js等多个调用方法。

    关键点总结:

    1. SFSmartStore 中的 - (id) initWithName:(NSString*)name user:(SFUserAccount *)user isGlobal:(BOOL)isGlobal 函数,是关键入口点函数。
    2. SFSmartStore 中默认把FMDB 和 SQLChiper都引入了,因此FMDB可以调用自身的setKey函数对数据库进行加密操作(不引入SQLChiper库,FMDB就无法使用这个函数)。如果不使用SFSmartStore的类方法+ (void)setEncryptionKeyBlock:(SFSmartStoreEncryptionKeyBlock)newEncryptionKeyBlock;对_encryptionKeyBlock(返回一个加密用的key)进行指定,SFSmartStore就会使用com.salesforce.smartstore.encryption.keyLabel 作为默认的key。如果不需要使用加密功能,只需要把_encryptionKeyBlock的返回值设置为空字符串(oc里就是@"")。
    3. SFSmartStore 其实就是对FMDB的一层封装!
    4. 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 //排序字段名




    
    
    
  • 相关阅读:
    css实现文字相对于图片垂直居中
    node能做的性能优化
    vue.config.js中vue的配置
    react/vue项目腾讯云/阿里云服务器linux部署
    taro项目结构分析和坑
    vscode自动编译less
    css彩色字体
    微信小程序文件上传
    小程序html解析
    小程序表单
  • 原文地址:https://www.cnblogs.com/breezemist/p/5804165.html
Copyright © 2011-2022 走看看