博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS REST服务
阅读量:4109 次
发布时间:2019-05-25

本文共 7626 字,大约阅读时间需要 25 分钟。

做过iOS开发的人员都知道,iOS应用需要通过某种与远程Web服务器通信。有些应用可以在没有网络连接的情况下使用,只在网络连接可用时才与服务器同步数据的应用就是这样。当然还有一类应用需要在几乎连续的网络连接下才能为用户提供有效的价值。这类应用通常作为Web服务的移动客户端。

大部分iOS应用都要用到这种功能,折让iPhone成为有史以来最好的互联网连接设备。不过,由于设备总是在移动,连接和接收信号可能都很差。作为iOS开发者得确保应用的感知时间差不多恒定,就好像全部内容存储在本地一样。所以本地缓存数据就是来解决这个问题的。今天我们来看看iOS如何用缓存技术来结局很差的网络连接甚至无网络连接带来的问题。

REST

REST服务有三大特征:无状态,统一资源定位和可缓存。
无状态:每次API调用都被视作新的请求,服务器不会记录客户端上下文。客户端需要维护服务器的状态。
统一资源定位:URL是REST的参数。REST使用这种资源定位,而且不维护客户端状态。
可缓存:REST的响应是以一种统一的,双方一致同意的格式返回给客户端,这样能够更好地解耦。目前,最常用的是XML和JSON。

XML解析

XML解析最常见的就是DOM和SAX解析器。两者的区别就是SAX是一串流解析器,它逐句便利整个XML文档,通过回掉函数返回解析结果。大部分SAX解析器接受一个URL作为参数,解析完目标数据就将数据返回。之前说过NSXMLParser,通过代理的方式回调。

parserDidStartDocumentparserDidEndDocumentparser:didiStartElement:namespaceURL:qualifiedName:attributes:parser:didiEndElement:namespaceURL:qualifiedName:parser:foundCharacters:

DOM解析

需要先把XML整个文档加载到内存中才开始解析。其优势在于可以使用Xpath查询访问随机数据,不需要像SAX使用委托。对于iOS开发没有内置的DOM解析器。一般使用第三方包装器,我再网上看到有:基于libxml2的KissXML,TouchXML和GDataXML。

使用DOM解析可以让代码更加简洁。虽然在处理请求时会花费更多的执行时间,但是跟网络操作消耗的时间相比,简直微不足道。

不过,我在项目中用的是SAX解析。

JSON解析

相信做客户端开发的,一定都逃不过Json吧。苹果有自己的解析JSON框架,也是我们常用的NSJSONSerialization。还有很多不错的第三方框架:SBJson,JSONKit,TouchJSON。基本上都是提供基于NSString,NSArray,NSDictionary的分类扩展。我在项目中用的是苹果自带的。

// 将字典或者数组转化为JSON串- (NSData *)toJSONData:(id)theData{    NSError *error = nil;    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:theData                                                      options:NSJSONWritingPrettyPrinted                                                         error:&error];    if ([jsonData length] > 0 && error == nil){        return jsonData;    }else{        return nil;    }}使用这个方法的返回,我们就可以得到想要的JSON串NSString *jsonString = [[NSString alloc] initWithData:jsonData                                                 encoding:NSUTF8StringEncoding];// 将JSON串转化为字典或者数组- (id)toArrayOrNSDictionary:(NSData *)jsonData{    NSError *error = nil;    id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData                                                   options:NSJSONReadingAllowFragments error:&error];    if (jsonObject != nil && error == nil){        return jsonObject;    }else{        // 解析错误         return nil;    }}//将JSON串与NSArray和NSDictionary的操作进行封装1.将NSString转化为NSArray或者NSDictionary#import "NSString+JSONCategories.h"@implementation NSString(JSONCategories)-(id)JSONValue;{    NSData* data = [self dataUsingEncoding:NSUTF8StringEncoding];    __autoreleasing NSError* error = nil;    id result = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];    if (error != nil) return nil;    return result;}@end2.将NSArray或者NSDictionary转化为NSString#import "NSObject+JSONCategories.h"@implementation NSObject (JSONCategories)-(NSData*)JSONString;{    NSError* error = nil;    id result = [NSJSONSerialization dataWithJSONObject:self                                                options:kNilOptionserror:&error];    if (error != nil) return nil;    return result;}@end

之前说过NSURLConnection。但是,为了开发REST服务,用MKNetworkKit更加方便。封装了很多常用的功能:基本认证/摘要认证,表单发布,上传/下载文件。还可以使用队列来管理网络请求。

Note:与浏览器不同的是,大部分运营商网络都会限制并发数据连接的数量,在EDGE连接中不要进行1个以上的网络操作,在3G网络中不要使用2个以上的并发网络操作,在Wi-Fi连接中的并发网络操作数量不要超过6个。

缓存

为了改善性能,提高用户的体验质量,离线工作是重点。一般有两种缓存技术支持离线:

按需缓存:应用缓存起请求应答,和Web浏览器的工作原理一样
预缓存:缓存全部内容以便离线访问

按需缓存思想:把从服务器获取的内容以某种格式存放在本地文件系统,之后对于每次请求,检查缓存中是否存在这块数据,只有当数据不存在(或者过期)的情况下才从服务器获取。这样,缓存层就和处理器的高速缓存差不多。获取数据的速度比数据本身重要。按需缓存的工作原理类似浏览器,允许我们查看以前查看或者访问过的内容。我们开发中,通讯录,消息等这些都是采用的按需缓存,不需要后台线程做这件事,也可以在一个URL请求返回成功实现按需缓存。

预缓存思想:需要一个后台县城访问数据并以有意义的格式保存,本地缓存无需重新连接服务器就可以被编辑。对预缓存来说,数据丢失或者缓存不命中是不可接受的。CoreData (结构化数据)试试先这种缓存的一种方式。

沙盒文件:

每个ios应用都有自己的应用沙盒,应用沙盒就是文件系统目录,与其他应用的文件系统隔离,ios系统不允许访问其他应用的应用沙盒。在ios8中已经开放访问。

应用沙盒一般包括以下几个文件目录:应用程序包、Documents、Libaray(下面有Caches和Preferences目录)、tmp。

应用程序包:包含所有的资源文件和可执行文件。

Documents:保存应用运行时生成的需要持久化的数据,iTunes会自动备份该目录。苹果建议将程序中建立的或在程序中浏览到的文件数据保存在该目录下,iTunes备份和恢复的时候会包括此目录

tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也有可能会清除该目录下的文件,iTunes不会同步该目录。iphone重启时,该目录下的文件会丢失。

Library:存储程序的默认设置和其他状态信息,iTunes会自动备份该目录。

Libaray/Caches:存放缓存文件,iTunes不会备份此目录,此目录下文件不会在应用退出删除。一般存放体积比较大,不是特别重要的资源。

Libaray/Preferences:保存应用的所有偏好设置,ios的Settings(设置)应用会在该目录中查找应用的设置信息,iTunes会自动备份该目录。

沙盒文件目录获取代码:

//Home目录NSString *homeDirectory = NSHomeDirectory();

//Document目录NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *path = [paths objectAtIndex:0];

//Cache目录NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);

NSString *path = [paths objectAtIndex:0];

//Libaray目录NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);

NSString *path = [paths objectAtIndex:0];

//tmp目录

NSString *tmpDir = NSTemporaryDirectory();

就像我们实验室做的企业级通信APP,像用户的账号密码,登陆时需要的IP号和端口号,用户头像等这些信息都需要存放到Library/Cache下。而偏好设置像响铃,震动这些存放到Library/preference下。

而我们的源代码打包后放在应用程序包路径下。我们下载的文件,下载过程中会放在tmp下,下载完成再放到Library。

数据缓存方法

1)数据模型缓存

我们可以用NSKeyedArchiver来实现。首先需要把模型类进行编解码重写。也就是要遵循NSCoding协议。

@interface Student : NSObject 
@property (nonatomic, assign) int idNum;@property (nonatomic, copy) NSString *name;@end@implementation Student#pragma mark 编码 对对象属性进行编码的处理- (void)encodeWithCoder:(NSCoder *)aCoder{ [aCoder encodeInt:_idNum forKey:IDNUM]; [aCoder encodeObject:_name forKey:NAME];}#pragma mark 解码 解码归档数据来初始化对象- (id)initWithCoder:(NSCoder *)aDecoder{ if (self = [super init]) { _idNum = [aDecoder decodeIntForKey:IDNUM]; _name = [aDecoder decodeObjectForKey:NAME]; } return self;}@end

然后对模型对象进行序列化

//获得文件路径    NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];    NSString *filePath = [documentPath stringByAppendingPathComponent:@"file.archiver"];//归档(序列化)NSArray *archiveAry = @[@"jereh",@"ios"];if ([NSKeyedArchiver archiveRootObject: archiveAry toFile:filePath]) {}//解归档(反序列化)NSArray *unArchiveAry = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

2)直接对文件进行操作我们常用到的plist

创建文件->添加数据
读取:

//path 读取当前程序定义好的provinces.plist省份城市文件    NSString *path = [[NSBundle mainBundle] pathForResource:@"student" ofType:@"plist"];    NSDictionary *data = [NSDictionary dictionaryWithContentsOfFile:path];    self.studentContent = [NSArray arrayWithArray:[data objectForKey:@"student"]];//array数组的名称就叫student
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];//获取标准函数对象    NSMutableDictionary *default = [defaults objectForKey:@"xxx"];//通过对象获取名称下NSMutableDictionary数据    NSString *studentname= [default objectForKey:@"name"];

增删改查

[defaults setObject:@"kaka" forKey:@"newdata"];//添加id对象类型数据    [defaults objectForKey:@"newdata"];//获取对象类型数据    [defaults setDouble:2013 forKey:@"double"];//添加double类型数据    [defaults doubleForKey:@"double"];//获取double类型数据    [defaults setBool:NO forKey:@"BOOL"];//添加BOOL类型数据    [defaults boolForKey:@"BOOL"];//获取BOOL类型数据    [defaults setInteger:12 forKey:@"int"];//添加int类型数据    [defaults integerForKey:@"int"];//获取int类型数据    [defaults setFloat:0.23 forKey:@"float"];//添加Float类型数据    [defaults floatForKey:@"float"];//获取float类型数据    [defaults removeObjectForKey:@"newdata"];//删除对象数据

3)SQLite

项目中的sqlit3,简单说一下使用过程吧

使用的过程根据使用的函数大致分为如下几个过程:sqlite3_open()sqlite3_prepare()sqlite3_step()sqlite3_column()sqlite3_finalize()sqlite3_close()

具体的讲解,可以参考这微博主:

4) CoreData

CoreData更像是一个对象序列化框架,而不仅仅是一个数据库的API。我理解的是非关系型数据库的一种,采用key-value的形式存储。用CoreData保存数据,首先创建一个CoreData模型文件,创建实体和关系,然后写好保存和获取数据的方法。实现预缓存时需要定期删除不再需要的(过时的)数据,否则缓存会不断增长进而影响应用的性能。同步本地变更是通过追踪变更集并发送回服务器实现的。

5)数据模型缓存和URL缓存

按需缓存可以采用数据模型缓存或者URL缓存。使用哪一个取决于服务器的实现。URL缓存的实现原理和浏览器缓存或代理服务器缓存类似。当服务器遵循HTTP1.1时缓存规范,效果很好。如果是SOAP服务器则采用数据模型缓存。数据模型缓存允许客户端有缓存失效的情形,当采用URL缓存,服务器通过HTTP1.1的缓存控制头控制缓存失效。MKNetworkKit提供对HTTP1.1缓存标准的原生支持。

转载地址:http://hjtsi.baihongyu.com/

你可能感兴趣的文章
微信小程序picker隐藏年份
查看>>
快速了解 React Hooks 原理
查看>>
响应式布局
查看>>
百度云下载工具分享
查看>>
spark on yarn任务提交缓慢解决
查看>>
Filco圣手二代双模蓝牙机械键盘的连接方法
查看>>
pyspark学习笔记
查看>>
JDK源码那些事儿之PriorityBlockingQueue
查看>>
Docker那些事儿之镜像创建
查看>>
Docker那些事儿之编排工具docker-compose
查看>>
JDK源码那些事儿之SynchronousQueue上篇
查看>>
JDK源码那些事儿之SynchronousQueue下篇
查看>>
jq实现图片下载功能
查看>>
解决ueditor二次加载(getEditor)加载失败的问题
查看>>
MySQL数据库文件的移动和权限设置
查看>>
cURL无法访问TLS网站故障解决
查看>>
pip升级
查看>>
HttpClient 如何设置超时时间
查看>>
Springmvc配置定时任务注解开发
查看>>
win10启动telnet
查看>>