iOS Jsonjs解析数据编码类型出现NSTaggedPointerString类型数据,导致无法取出数据,该怎么解决呢?

Pages: 1/2
主题 : NSDictionary中Key值出现nstaggedpointerstring类型
级别: 新手上路
UID: 313694
可可豆: 91 CB
威望: 78 点
在线时间: 155(时)
发自: Web Page
来源于&&分类
NSDictionary中Key值出现nstaggedpointerstring类型&&&
服务器发来的json数据,id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];直接解析成NSDictionary类型
部分key变成了nstaggedpointerstring类型这样通过已知的key就无法取到值,如[d objectForKey:@&sale_day&]就取不到值问题:1、服务器端并没有做什么特殊处理,为什么会出现这样的key值?2、这种情况要怎么处理?
级别: 新手上路
可可豆: 1 CB
威望: 1 点
在线时间: 8(时)
发自: Web Page
遇到同样的问题,楼主解决了,记得发一下解决方法
级别: 新手上路
UID: 300900
可可豆: 16 CB
威望: 3 点
在线时间: 28(时)
发自: Web Page
楼主解决了么,同问啊!
级别: 新手上路
可可豆: 1 CB
威望: 1 点
在线时间: 5(时)
发自: Web Page
请问留住解决了吗,遇到了同样的问题,暂时没办法解决,求楼主分享
级别: 新手上路
可可豆: 2 CB
威望: 2 点
在线时间: 51(时)
发自: Web Page
楼主解决了吗?同问啊
级别: 新手上路
UID: 530627
可可豆: 12 CB
威望: 12 点
在线时间: 322(时)
发自: Web Page
你这个字典的前一级应该不是数组,本身就是字典吧?我这里就是这样的问题,后台给的数据,他们那里显示的是array,其实在iOS开发这里是字典。
级别: 新手上路
可可豆: 59 CB
威望: 59 点
在线时间: 24(时)
发自: Web Page
楼主解决了吗?同问
级别: 新手上路
可可豆: 2 CB
威望: 2 点
在线时间: 12(时)
发自: Web Page
楼主解决了么 同问
级别: 新手上路
可可豆: 2 CB
威望: 2 点
在线时间: 140(时)
发自: iPhone
你看下属性类型是否设置对了,是不是字典类型,前边是否加*了
级别: 新手上路
UID: 432593
可可豆: 4 CB
威望: 5 点
在线时间: 152(时)
发自: Web Page
楼主解决了吗?
Pages: 1/2
关注本帖(如果有新回复会站内信通知您)
发帖、回帖都会得到可观的积分奖励。
按"Ctrl+Enter"直接提交
关注CocoaChina
关注微信 每日推荐
扫一扫 关注CVP公众号
扫一扫 浏览移动版iOS&网络数据访问,json的解析
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。__NSTaggedPointerString 转码问题 - CSDN博客
__NSTaggedPointerString 转码问题
__NSTaggedPointerString
这个类型是标签指针字符串,这是苹果在 64 位环境下对 NSString,NSNumber 等对象做的一些优化。简单来讲可以理解为把指针指向的内容直接放在了指针变量的内存地址中,因为在 64 位环境下指针变量的大小达到了 8 位足以容纳一些长度较小的内容。于是使用了标签指针这种方式来优化数据的存储方式。从他的引用计数可以看出,这货也是一个释放不掉的单例常量对象。在运行时根据实际情况创建。
对于 NSString 对象来讲,当非字面值常量的数字,英文字母字符串的长度小于等于 9 的时候会自动成为 NSTaggedPointerString 类型.
如果有中文或其他特殊符号(可能是非 ASCII 字符)存在的话则会直接成为 )__NSCFString 类型。
这种对象被直接存储在指针的内容中,可以当作一种伪对象
本文已收录于以下专栏:
相关文章推荐
转自:/ios/49.html
本文由CocoaChina译者@ALEX吴浩文翻译
作者:Mike Ash  
浅拷贝 & 深拷贝 
copy 就是浅拷贝, 因为没有产生新的对象(有没有产生新的对象也是判断深浅拷贝的标准)
mutableCopy 就是深拷贝, 会再内存中重新分配一块内存空间.
不知道为什么
升级到xcode7之后,你会神奇的发现你的项目会奔溃到jsonkit里,报thread 1:exc_bad_access(codeexc_i386_gpflt)野指针错误
根据奔溃到jsonkit....
今天在解析json数据的时候得到了一堆这样的数据:{&errNum&:0,&errMsg&:&success&,&retData&:[{&title&:&\uf\u54c1...
title: 关于hive中decode函数,默认转码没有GBK中文字符集的问题今天要分享的内容是hive的select查询中的decode函数,对url进行转码的查询,看了官方文档,心都凉了,如下 ...
他的最新文章
讲师:宋宝华
讲师:何宇健
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)实际项目中的 MVVM(积木)模式第二章:model --如何高效利用数据层 - IOS - 伯乐在线
& 实际项目中的 MVVM(积木)模式第二章:model –如何高效利用数据层
“不为炫技而炫技,不为架构而设计架构,只为写出一个接地气、通俗易懂的使用方法”
(注:了解整个设计模式体系请查看我上篇文章)
这篇文章讲解Model和ViewModel。
本着易扩展、易理解的前提,讲解中Model和ViewModel都用最基础的方法和易理解的思维图。
为何为何会将View和ViewModel合并在一起讲解?为何我会将有些文章说的的网络层与数据层合并一起叫数据层?
很简单,我们需要明白一个道理,无论是网络请求还是本地缓存,本质上都是传递数据;因此,我们要做的就是将各种来源的数据通过数据加工(ViewModel)形成统一的格式(Model)再通过一个统一的接口传递给需要的地方。我所讲的数据层,我把这形象地叫为数据工厂。
首先,我们先开始说说:Model。
一、Model–项目的信息承载与传递者
一个多人协同开发的项目,保证数据结构的一致性和稳定是很有必要的。而Model则是很好的实现了这一需求。
首先,我们先通过三个大的方面将字典与Model作一个比较,更直观了解Model的特点。
1、字典与模型的比较
a、取值:字典会因为没有取值的这个key或者这个错误的key刚好是这个字典中其他类型的值对应的key(因输入错误等原因),通过这个key取出来的值为nil或者其他类型的值,如赋值给label之类的文字控件,可能会导致程序崩溃,而Model不会出现这样的问题;
b、数据展示:字典无法再不改变数据源的前提下,改变数据的格式,而Model则可以通过get方法实现这个需求,保证了数据的原始性和可变性;
c、后期维护:字典每个key的具体含义和有多少key要通过接口文档去了解,而Model体现在具体的属性和每个属性的备注上;
可能有同学会问建立Model一个个去复制粘贴属性好麻烦,还有像数据缓存之类还要一个个写解挡归档好麻烦呢/(ㄒoㄒ)/~~
这么多好的优点的前提下,这几个小麻烦肯定会通过方法解决噻,且看下面:
2、解决Model的一些小麻烦
a、如何快速建立Model:这里有份代码,可以将网络请求下来的字典里的key在控制台打印成Model里的属性格式哦。(打印效果在代码块下面)
Objective-C
- (void)writeInfoWithDict:(NSDictionary *)dict
NSMutableString *strM = [NSMutableString string];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSLog(@"%@,%@",key,[obj class]);
NSString *className = NSStringFromClass([obj class]) ;
if ([className isEqualToString:@"__NSCFString"] | [className isEqualToString:@"__NSCFConstantString"] | [className isEqualToString:@"NSTaggedPointerString"]) {
[strM appendFormat:@"@property (nonatomic, copy) NSString *%@;\\\\n",key];
}else if ([className isEqualToString:@"__NSCFArray"] |
[className isEqualToString:@"__NSArray0"] |
[className isEqualToString:@"__NSArrayI"]){
[strM appendFormat:@"@property (nonatomic, strong) NSArray *%@;\\\\n",key];
}else if ([className isEqualToString:@"__NSCFDictionary"]){
[strM appendFormat:@"@property (nonatomic, strong) NSDictionary *%@;\\\\n",key];
}else if ([className isEqualToString:@"__NSCFNumber"]){
[strM appendFormat:@"@property (nonatomic, copy) NSNumber *%@;\\\\n",key];
}else if ([className isEqualToString:@"__NSCFBoolean"]){
[strM appendFormat:@"@property (nonatomic, assign) BOOL
%@;\\\\n",key];
}else if ([className isEqualToString:@"NSDecimalNumber"]){
[strM appendFormat:@"@property (nonatomic, copy) NSString *%@;\\\\n",[NSString stringWithFormat:@"%@",key]];
else if ([className isEqualToString:@"NSNull"]){
[strM appendFormat:@"@property (nonatomic, copy) NSString *%@;\\\\n",[NSString stringWithFormat:@"%@",key]];
}else if ([className isEqualToString:@"__NSArrayM"]){
[strM appendFormat:@"@property (nonatomic, strong) NSMutableArray *%@;\\\\n",[NSString stringWithFormat:@"%@",key]];
NSLog(@"\\\\n\\\\n%@\\\\n",strM);
123456789101112131415161718192021222324252627282930313233
- (void)writeInfoWithDict:(NSDictionary *)dict{&&&&NSMutableString *strM = [NSMutableString string];&&&&&[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {&&&&&&&&//&&NSLog(@"%@,%@",key,[obj class]);&&&&&&&&&NSString *className = NSStringFromClass([obj class]) ;&&&&&&&&&if ([className isEqualToString:@"__NSCFString"] | [className isEqualToString:@"__NSCFConstantString"] | [className isEqualToString:@"NSTaggedPointerString"]) {&&&&&&&&&&&&[strM appendFormat:@"@property (nonatomic, copy) NSString *%@;\\\\n",key];&&&&&&&&}else if ([className isEqualToString:@"__NSCFArray"] |&&&&&&&&&&&&&&&&&&[className isEqualToString:@"__NSArray0"] |&&&&&&&&&&&&&&&&&&[className isEqualToString:@"__NSArrayI"]){&&&&&&&&&&&&[strM appendFormat:@"@property (nonatomic, strong) NSArray *%@;\\\\n",key];&&&&&&&&}else if ([className isEqualToString:@"__NSCFDictionary"]){&&&&&&&&&&&&[strM appendFormat:@"@property (nonatomic, strong) NSDictionary *%@;\\\\n",key];&&&&&&&&}else if ([className isEqualToString:@"__NSCFNumber"]){&&&&&&&&&&&&[strM appendFormat:@"@property (nonatomic, copy) NSNumber *%@;\\\\n",key];&&&&&&&&}else if ([className isEqualToString:@"__NSCFBoolean"]){&&&&&&&&&&&&[strM appendFormat:@"@property (nonatomic, assign) BOOL&& %@;\\\\n",key];&&&&&&&&}else if ([className isEqualToString:@"NSDecimalNumber"]){&&&&&&&&&&&&[strM appendFormat:@"@property (nonatomic, copy) NSString *%@;\\\\n",[NSString stringWithFormat:@"%@",key]];&&&&&&&&}&&&&&&&&else if ([className isEqualToString:@"NSNull"]){&&&&&&&&&&&&[strM appendFormat:@"@property (nonatomic, copy) NSString *%@;\\\\n",[NSString stringWithFormat:@"%@",key]];&&&&&&&&}else if ([className isEqualToString:@"__NSArrayM"]){&&&&&&&&&&&&[strM appendFormat:@"@property (nonatomic, strong) NSMutableArray *%@;\\\\n",[NSString stringWithFormat:@"%@",key]];&&&&&&&&}&&&&&}];&&&&&&&& NSLog(@"\\\\n\\\\n%@\\\\n",strM);}
看下图打印效果,那么打印出来的效果大家知道了吧,直接复制粘贴就OK啦:
b、怎么解决繁琐的解挡归档呢
在BaseModel(Model的基类)中写一个统一的解挡、归档,这里就要用到runtime中非常有用的两个方法:
Objective-C
class_copyIvarList(Class cls, unsigned int *outCount) //遍历该类成员变量列表
class_copyIvarList(Class cls, unsigned int *outCount) //遍历该类成员变量列表
Objective-C
ivar_getName(Ivar v) //获取该类某个成员变量的名字
ivar_getName(Ivar v) //获取该类某个成员变量的名字
那么具体怎么在基类写一个,所有适用呢,且看下面:
Objective-C
- (void)encodeWithCoder:(NSCoder *)encoder
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i = 0; i& i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithUTF8String:name];
id value = [self valueForKey:key];
[encoder encodeObject:value forKey:key];
free(ivars);
- (id)initWithCoder:(NSCoder *)decoder
if (self = [super init]) {
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i = 0; i& i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [NSString stringWithUTF8String:name];
id value = [decoder decodeObjectForKey:key];
[self setValue:value forKey:key];
free(ivars);
12345678910111213141516171819202122232425262728293031323334
- (void)encodeWithCoder:(NSCoder *)encoder{&&&&unsigned int count = 0;&&&&Ivar *ivars = class_copyIvarList([self class], &count);&&&&&for (int i = 0; i&count; i++) {&&&&&&&&Ivar ivar = ivars[i];&&&&&&&&const char *name = ivar_getName(ivar);&&&&&&&&// 归档&&&&&&&&NSString *key = [NSString stringWithUTF8String:name];&&&&&&&&id value = [self valueForKey:key];&&&&&&&&[encoder encodeObject:value forKey:key];&&&&}&&&&&free(ivars);}&- (id)initWithCoder:(NSCoder *)decoder{&&&&if (self = [super init]) {&&&&&&&&unsigned int count = 0;&&&&&&&&Ivar *ivars = class_copyIvarList([self class], &count);&&&&&&&&for (int i = 0; i&count; i++) {&&&&&&&&&&&&Ivar ivar = ivars[i];&&&&&&&&&&&&const char *name = ivar_getName(ivar);&&&&&&&&&&&&// 解档&&&&&&&&&&&&NSString *key = [NSString stringWithUTF8String:name];&&&&&&&&&&&&id value = [decoder decodeObjectForKey:key];&&&&&&&&&&&&[self setValue:value forKey:key];&&&&&&&&}&&&&&&&&free(ivars);&&&&} &&&&return self; }
至此,所有继承于这个Model基类的Model都自动实现了解档归档的方法。
既然解决了建立Model的一些小麻烦,我们就来构建一个项目中标准的BaseModel(基类模型)。
3、何为基类Model建立要求?
a、数据格式读取统一与写入统一;
b、模型属性值可批量修改;
这样才能保证在“千奇百怪、朝令夕改”的数据源中,进入到这个项目体系后,面向业务工程师的时候,是统一整齐的标准模型,然后业务工程师才会在这个基础之上扩展其他子Model。
其中读写统一则是通过上面的解档归档解决,而模型属性值批量修改则是通过李明杰大神的MJExtension(这个三方库可以在不用继承其他Model前提下使用,保证了Model独立性),具体代码在BaseModel如下:
Objective-C
- (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property
if ([property.name isEqualToString:@"buy_price"]|| [property.name isEqualToString:@"buy_sale_price"]||[property.name isEqualToString:@"info_price"]||[property.name isEqualToString:@"sale_price"] ) {
if (oldValue == nil || [oldValue isKindOfClass:[NSNull class]])
return @"价格面议";
}//可将所有模型在生成时将涉及相应字段的值变成“价格面议”
else if (property.type.typeClass ==[NSString class]) {
if (oldValue == nil || [oldValue isKindOfClass:[NSNull class]])
return @"--";//可将所有模型在生成时将string类型从nil或Null变成“--”
} else if (property.type.typeClass == [NSArray class]) {
if (oldValue == nil)
return [[NSArray alloc] init];//可将所有模型在生成时将array类型从nil变成[[NSArray alloc] init]
return oldV
1234567891011121314151617
- (id)mj_newValueFromOldValue:(id)oldValue property:(MJProperty *)property{&&&&if ([property.name isEqualToString:@"buy_price"]|| [property.name isEqualToString:@"buy_sale_price"]||[property.name isEqualToString:@"info_price"]||[property.name isEqualToString:@"sale_price"] ) {&&&&&&&&if (oldValue == nil || [oldValue isKindOfClass:[NSNull class]])&&&&&&&&&&&&return @"价格面议";&&&&}//可将所有模型在生成时将涉及相应字段的值变成“价格面议”&&&& else if (property.type.typeClass ==[NSString class]) {&&&&&&&&if (oldValue == nil || [oldValue isKindOfClass:[NSNull class]])&&&&&&&&&&&&&return @"--";//可将所有模型在生成时将string类型从nil或Null变成“--”&&&&} else if (property.type.typeClass == [NSArray class]) {&&&&&&&&if (oldValue == nil)&&&&&&&&&&&&return [[NSArray alloc] init];//可将所有模型在生成时将array类型从nil变成[[NSArray alloc] init]&&&&}&&&&&return oldValue;}
以上代码举了部分替换的例子,目的是告诉大家通过这方法可以在数据源传给客户端是非友好数据的时候,我们客户端能够进行处理,给业务工程师一个友好的数据。这对数据工厂这个模式来说是非常有必要的。
至此,BaseModel就只有写两个方法:解档与归档 以及 属性值批量修改。因为我们始终要明白:Model是来保证整个项目架构数据结构的一致性和稳定性。那么继承这个BaseModel的子Model就都具备了面向业务工程师友好数据的特点。
那么如何正确使用子Model呢?
我举两个例子:
1、如何将模型源数据的时间
变成 (正确使用get方法)
Objective-C
- (NSString *)pub_date{
return [_pub_date formatDateString];//formatDateString是NSString的Category
- (NSString *)pub_date{&&&&&return [_pub_date formatDateString];//formatDateString是NSString的Category&}
这样的好处有两方面:一方面,业务工程师不会修改源数据,保证了源数据的安全性;另一方面,类似formatDateString的方法,是通过Category(也就是我后面要说的工具类)使用的,保证了代码的低耦合性。
2、使用子Model分离数据的一个例子(这个例子感谢我的同事 张尔柏 同学提供,展示这个例子主要目的是为了表达子Model其中一个在cell样式数据分离的作用,可能会因为没有demo,大家不太好理解。所以,大家可以在后期demo上传后再次详细了解)
这里我们举个tableView中Cell显示(整个tableView的demo将会在View篇结束后放出),其中Model要做的事情,我们先看在Model中的代码:
Objective-C
- (void)setupInfo {
self.xibName = @"SaleInfoTableViewCell";/指定Cell的Cell样式
self.cellHeight = @(76);//指定Cell的高度
self.ideltifier = @"cell";//指定Cell的ideltifier
- (void)setupInfo {&&&&self.xibName = @"SaleInfoTableViewCell";/指定Cell的Cell样式&&&&self.cellHeight = @(76);//指定Cell的高度&&&&self.ideltifier = @"cell";//指定Cell的ideltifier}
通过在Model生成时执行这个方法,实现了Cell样式与样式数据分离,做到了每个Cell的View样式与Model的绑定。
在讲解Model的结尾,总结起来就是:Model存在的目的是为了给业务工程师一个友好稳定的数据,让业务工程师在相应的模块内独立地做相应的数据操作。
二、ViewModel–做一个优秀的数据工厂
如文章开始的图就知道,ViewModel更像一个食品工厂一样,将不同的原料通过不同的制作工艺产出为统一的产品。
那么作为工厂的框架BaseViewModel应该是怎样的呢?
首先我们应该先想到,我们的原料(数据)来自哪里?
基本都是来自网络了噻!
既然来自网络,那么就明确了BaseViewModel应该实现三个事情:网络通信、上传、下载。(都用af第三方库实现)
废话不多说,直接上代码:
1、BaseViewModel实现的三个方法
网络请求:
Objective-C
- (void)serviceNetWorkWithUrlStr:(NSString *)urlStr//请求网络地址
Params:(NSMutableDictionary *)params//请求参数
Success:(void(^)(id result))successBlock
Failure:(void(^)(NSError *error))failBlock {
AFHTTPRequestOperationManager * manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer.timeoutInterval = 10;//请求时长
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
//如果需要加解密,可引入加解密的工具类将params加密实现
[manager POST:urlStr parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
successBlock(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@", [error localizedDescription]);
failBlock(error);
123456789101112131415161718
- (void)serviceNetWorkWithUrlStr:(NSString *)urlStr//请求网络地址&&&&&&&&&&&&&&&&&&&&&&&&&&Params:(NSMutableDictionary *)params//请求参数&&&&&&&&&&&&&&&&&&&&&&&& Success:(void(^)(id result))successBlock&&&&&&&&&&&&&&&&&&&&&&&& Failure:(void(^)(NSError *error))failBlock {&&&&AFHTTPRequestOperationManager * manager = [AFHTTPRequestOperationManager manager];&&&&manager.requestSerializer.timeoutInterval = 10;//请求时长&&&&manager.requestSerializer = [AFHTTPRequestSerializer serializer];&&&&manager.responseSerializer = [AFHTTPResponseSerializer serializer];//如果需要加解密,可引入加解密的工具类将params加密实现&&&&[manager POST:urlStr parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {&&&&&&&&successBlock(responseObject);&&&&&} failure:^(AFHTTPRequestOperation *operation, NSError *error) {&&&&&&&&NSLog(@"%@", [error localizedDescription]);&&&&&&&&failBlock(error);&&&&}];&}
该上传方法需要求能同时多传,且传不同类型的文件,以适应不用的场景需要
Objective-C
- (void)uploadFileWithfileList:(NSMutableArray *)params//存放上传文件的数组
Option:(NSDictionary *)optiondic//请求参数
Url:(NSString *)requestURL//上传网络地址
Success:(void(^)(id responseObject))successBlock
Failure:(void(^)(NSError *error))failBlock
progress:(void (^)(float progress))progress{
AFHTTPRequestOperationManager *manager=[AFHTTPRequestOperationManager manager];
//设置返回的数据解析格式
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];
AFHTTPRequestOperation *operation = [manager POST:requestURL parameters:optiondic constructingBodyWithBlock:^(id&AFMultipartFormData& formData) {
//下方举了一个极端例子:当数组里存放了不同类型的文件如何上传
for (int i = 0; i&params. i++) {
if ([params[i] isKindOfClass:[UIImage class]]) {
UIImage *image = [params[i] imageCompressForWidth:params[i] targetWidth:375];
NSData *imageData =UIImagePNGRepresentation(image);
[formData appendPartWithFileData:imageData name:@"file_content" fileName:[NSString stringWithFormat:@"anyImage_%d.png",i] mimeType:@"image/png"];
}else if ([params[i] isKindOfClass:[NSString class]]) {
NSURL *url = [NSURL fileURLWithPath:params[i]];
NSData *data = [NSData dataWithContentsOfURL:url];
[formData appendPartWithFileData:data name:@"file_content" fileName:@"11.aac" mimeType:@"audio/x-mei-aac"];
}else if ([params[i] isKindOfClass:[NSURL class]]) {
NSData *data = [NSData dataWithContentsOfURL:params[i]];
[formData appendPartWithFileData:data name:@"file_content" fileName:@"11.aac" mimeType:@"audio/x-mei-aac"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
successBlock(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failBlock(error);
//获得上传进度
[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
NSLog(@"百分比:%f",totalBytesWritten*1.0/totalBytesExpectedToWrite);
progress(totalBytesWritten*1.0/totalBytesExpectedToWrite);
1234567891011121314151617181920212223242526272829303132333435363738394041424344
- (void)uploadFileWithfileList:(NSMutableArray *)params//存放上传文件的数组&&&&&&&&&&&&&&&&&&&&&&Option:(NSDictionary *)optiondic//请求参数&&&&&&&&&&&&&&&&&&&&&& Url:(NSString *)requestURL//上传网络地址&&&&&&&&&&&&&&&&&&&&&&&& Success:(void(^)(id responseObject))successBlock&&&&&&&&&&&&&&&&&&&&&&&& Failure:(void(^)(NSError *error))failBlock&&&&&&&&&&&&&&&&&&&&&&&& progress:(void (^)(float progress))progress{&&&&AFHTTPRequestOperationManager *manager=[AFHTTPRequestOperationManager manager];&&&&//设置返回的数据解析格式&&&&manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];&&&&manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"application/json"];&&&&AFHTTPRequestOperation *operation = [manager POST:requestURL parameters:optiondic constructingBodyWithBlock:^(id&AFMultipartFormData& formData) {&&&&&& //下方举了一个极端例子:当数组里存放了不同类型的文件如何上传&&&&&&&&for (int i = 0; i&params.count; i++) {&&&&&&&&&&&&if ([params[i] isKindOfClass:[UIImage class]]) {&&&&&&&&&&&&&&&&&UIImage *image = [params[i] imageCompressForWidth:params[i] targetWidth:375];&&&&&&&&&&&&&&&&NSData *imageData =UIImagePNGRepresentation(image);&&&&&&&&&&&&&&&&[formData appendPartWithFileData:imageData name:@"file_content" fileName:[NSString stringWithFormat:@"anyImage_%d.png",i] mimeType:@"image/png"];&&&&&&&&&&&&}else if ([params[i] isKindOfClass:[NSString class]]) {&&&&&&&&&&&&&&&&NSURL *url = [NSURL fileURLWithPath:params[i]];&&&&&&&&&&&&&&&&NSData *data = [NSData dataWithContentsOfURL:url];&&&&&&&&&&&&&&&&[formData appendPartWithFileData:data name:@"file_content" fileName:@"11.aac" mimeType:@"audio/x-mei-aac"];&&&&&&&&&&&&&}else if ([params[i] isKindOfClass:[NSURL class]]) {&&&&&&&&&&&&&&&&NSData *data = [NSData dataWithContentsOfURL:params[i]];&&&&&&&&&&&&&&&&[formData appendPartWithFileData:data name:@"file_content" fileName:@"11.aac" mimeType:@"audio/x-mei-aac"];&&&&&&&&&&&&}&&&&&&&&&}&&&&} success:^(AFHTTPRequestOperation *operation, id responseObject) {&&&&&&&&&successBlock(responseObject);&&&&&} failure:^(AFHTTPRequestOperation *operation, NSError *error) {&&&&&&&&failBlock(error);&&&&}];&&&&//获得上传进度&&&&[operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {&&&&&&&&NSLog(@"百分比:%f",totalBytesWritten*1.0/totalBytesExpectedToWrite);&&&&&&&&progress(totalBytesWritten*1.0/totalBytesExpectedToWrite);&&&&&&}];}
Objective-C
- (void)downloadFileWithOption:(NSDictionary *)paramDic//请求参数
withUrl:(NSString*)requestURL//下载地址
savedPath:(NSString*)savedPath//保存路径
downloadSuccess:(void (^)(id responseObject))success
downloadFailure:(void (^)(NSError *error))failure
progress:(void (^)(float progress))progress
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
NSMutableURLRequest *request =[serializer requestWithMethod:@"POST" URLString:requestURL parameters:paramDic error:nil];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request];
[operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:savedPath append:NO]];
[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {
float p = (float)totalBytesRead / totalBytesExpectedToR
progress(p);//下载进度
NSLog(@"download:%f", (float)totalBytesRead / totalBytesExpectedToRead);
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
success(responseObject);
NSLog(@"下载成功");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
failure(error);
NSLog(@"下载失败");
[operation start];
12345678910111213141516171819202122232425262728293031323334
- (void)downloadFileWithOption:(NSDictionary *)paramDic//请求参数&&&&&&&&&&&&&&&& withUrl:(NSString*)requestURL//下载地址&&&&&&&&&&&&&&&&&&&& savedPath:(NSString*)savedPath//保存路径&&&&&&&&&&&&&& downloadSuccess:(void (^)(id responseObject))success&&&&&&&&&&&&&& downloadFailure:(void (^)(NSError *error))failure&&&&&&&&&&&&&&&&&&&&&&progress:(void (^)(float progress))progress&{&&&&AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];&&&&NSMutableURLRequest *request =[serializer requestWithMethod:@"POST" URLString:requestURL parameters:paramDic error:nil];&&&&AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request];&&&&[operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:savedPath append:NO]];&&&&[operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {&&&&&&&&float p = (float)totalBytesRead / totalBytesExpectedToRead;&&&&&&&&progress(p);//下载进度&&&&&&&&NSLog(@"download:%f", (float)totalBytesRead / totalBytesExpectedToRead);&&&&&}];&&&&&[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {&&&&&&&&success(responseObject);&&&&&&&&NSLog(@"下载成功");&&&&&} failure:^(AFHTTPRequestOperation *operation, NSError *error) {&&&&&&&&failure(error);&&&&&&&&&NSLog(@"下载失败");&&&&&}];&&&&&[operation start];&&}
2.如何写好一个子ViewModel
不知道大家注意到没有,其实我们真实的项目中,网络请求返回来的状态其实可能是会存在三种状态的:请求成功;请求失败,服务器返回错误信息;请求失败,网络不通。同时,我们会在某些地方做缓存读写。那既然如此,继承BaseViewModel的子ViewModel的对外接口(唯一对外接口)应是如下所写:
Objective-C
- (void)serviceNetWorkMessageListWith
Success:(void(^)(id responseObject))successBlock//请求成功回调
ReceiveFail:(void (^)(id responseObject))ReceiveFailBolck//请求失败,服务器返回错误信息
Failure:(void(^)(NSError *error))failBlock//请求失败,网络不通 {
NSMutableDictionary *tempDic = [@{@"service_code":Message_Service_Code} mutableCopy];
addEntriesFromDictionary:[self getPrivateParameters]]//所有接口的公共访问参数;
[tempDic addEntriesFromDictionary:@{"":""}//对应接口的对应参数];
//这里举个Archive做数据缓存的读取与存储的例子,方便大家理解在某些场景下需要某个ViewModel作缓存时,如何只对外提供一个数据接口,里面作多级缓存的原理,具体实现大家可以结合自身优化,比如数据库的缓存,比如在这个类单独归一个方法。
if ([[NSUserDefaults standardUserDefaults] objectForKey:Message_Service_Code]) {
NSArray *priarr = [[NSUserDefaults standardUserDefaults] objectForKey:Message_Service_Code];
NSMutableArray *priMuarr = [NSMutableArray arrayWithCapacity:0];
for (NSData *data in priarr) {
MessageInfoModel *message =
[NSKeyedUnarchiver unarchiveObjectWithData:data];//解档
[priMuarr addObject:message];
successBlock(priMuarr);//返回缓存数据
[self serviceNetWorkWithUrlStr:[UrlGenerator queryNewMessageUrl] Params:tempDic Success:^(id responseObject) {
if ([responseObject[@"code"] isEqualToString:@"0000"]) {
NSArray *array = [MessageInfoModel mj_objectArrayWithKeyValuesArray:responseObject[@"data"]];
NSMutableArray *enArr = [NSMutableArray arrayWithCapacity:0];
for (MessageInfoModel *messageModel in array) {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:messageModel];
[enArr addObject:data];//归档
[[NSUserDefaults standardUserDefaults] setObject:enArr forKey:Message_Service_Code];
successBlock(array);//返回网络请求数据
ReceiveFailBolck(responseObject[@"msg"]);
} Failure:^(NSError *error) {
failBlock(error);
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
- (void)serviceNetWorkMessageListWith&&&&&&&&&&&&&&&&&&&&&&&&&&&& Success:(void(^)(id responseObject))successBlock//请求成功回调&&&&&&&&&&&&&&&&&&&&&&&& ReceiveFail:(void (^)(id responseObject))ReceiveFailBolck//请求失败,服务器返回错误信息&&&&&&&&&&&&&&&&&&&&&&&&&&&& Failure:(void(^)(NSError *error))failBlock//请求失败,网络不通 {&&&&NSMutableDictionary *tempDic = [@{@"service_code":Message_Service_Code} mutableCopy];&&&&[tempDic&&addEntriesFromDictionary:[self getPrivateParameters]]//所有接口的公共访问参数;&&&&[tempDic addEntriesFromDictionary:@{"":""}//对应接口的对应参数];//这里举个Archive做数据缓存的读取与存储的例子,方便大家理解在某些场景下需要某个ViewModel作缓存时,如何只对外提供一个数据接口,里面作多级缓存的原理,具体实现大家可以结合自身优化,比如数据库的缓存,比如在这个类单独归一个方法。if ([[NSUserDefaults standardUserDefaults] objectForKey:Message_Service_Code]) {&&&&&&&&&&&&&&&&NSArray *priarr = [[NSUserDefaults standardUserDefaults] objectForKey:Message_Service_Code];&&&&&&&&&&&&&&&&NSMutableArray *priMuarr = [NSMutableArray arrayWithCapacity:0];&&&&&&&&&&&&&&&&for (NSData *data in priarr) {&&&&&&&&&&&&&&&&&&&&&MessageInfoModel *message =&&[NSKeyedUnarchiver unarchiveObjectWithData:data];//解档&&&&&&&&&&&&&&&&&&&&[priMuarr addObject:message];&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&successBlock(priMuarr);//返回缓存数据&&&&&&&&&&&&}&&&&[self serviceNetWorkWithUrlStr:[UrlGenerator queryNewMessageUrl] Params:tempDic Success:^(id responseObject) {& if ([responseObject[@"code"] isEqualToString:@"0000"]) {&&&&&&&&&&&&&&NSArray *array = [MessageInfoModel mj_objectArrayWithKeyValuesArray:responseObject[@"data"]];&&&&&&&&&&&&NSMutableArray *enArr = [NSMutableArray arrayWithCapacity:0];&&&&&&&&&&&&for (MessageInfoModel *messageModel in array) {&&&&&&&&&&&&&&&&&&NSData *data = [NSKeyedArchiver archivedDataWithRootObject:messageModel];&&&&&&&&&&&&&&&&[enArr addObject:data];//归档&&&&&&&&&&&&&&}&&&&&&&&&&&&[[NSUserDefaults standardUserDefaults] setObject:enArr forKey:Message_Service_Code];&&&&&&&&&&&&successBlock(array);//返回网络请求数据&&&&&&&&&&}else {&&&&&&&&&&&&&ReceiveFailBolck(responseObject[@"msg"]);&&&&&&&&}&&&&&&} Failure:^(NSError *error) {&&&&&&&&failBlock(error);&&&&}];}
3、到底ViewModel放在哪里合适?创建多少个ViewModel合适?
开门见山直说,个人认为只要涉及数据的View的模块,最理想的情况应该一个View模块一个ViewModel。
因为,只有这样,在后期项目越来越庞大,维护的人员越来越多的时候,才能保证模块之间的绝对独立。
(如果是一两个人开发的中小型项目,也没必要一个模块对一个ViewModel,本身功能不多,没有必要。这时可以一个Controller对一个ViewModel,或者几个同需求功能的Controller对一个ViewModel。项目死的,人是灵活的,具体情况具体分析。)
我举两个例子:
a.某个模块因为维护人员频次多,需求改动频繁,到最后需要大改某个模块的时候,因为之前的至上到下(数据到界面)的绝对独立,可以完全抽出来,重新制作一个新的模块,重新替换进去;
b.某些模块需要数据缓存,某些模块又需要网络状态判断(含大图片展示的模块),完全可以针对不同情况针对这些相应模块对应的ViewModel数据工厂做相应的事情。
以上两个例子,我想做过项目的,尤其是遇到频繁更改需求的,应该是深有体会(哎,我本人就特别有体会/(ㄒoㄒ)/~~)。
借用一位大神的话结束Model篇:
“你必须得清楚你要做什么,业务方希望要什么。而不是为了架构而架构,也不是为了体验新技术而改架构方案。以前是MVC,最近流行MVVM,如果过去的MVC是个好架构,没什么特别大的缺陷,就不要推倒然后搞成MVVM。”
后面几天我在各位大神的建议下会不断优化文章各个细节,欢迎多多关注,共同学习。几天后会发出 view–业务与界面结合的模块开发 请多关注。
可能感兴趣的话题
o 102 回复
关于iOS频道
iOS频道分享iOS和Swift开发,应用设计和推广,iOS相关的行业动态。
新浪微博:
推荐微信号
(加好友请注明来意)
– 好的话题、有启发的回复、值得信赖的圈子
– 分享和发现有价值的内容与观点
– 为IT单身男女服务的征婚传播平台
– 优秀的工具资源导航
– 翻译传播优秀的外文文章
– 国内外的精选文章
– UI,网页,交互和用户体验
– 专注iOS技术分享
– 专注Android技术分享
– JavaScript, HTML5, CSS
– 专注Java技术分享
– 专注Python技术分享
& 2017 伯乐在线

我要回帖

更多关于 js解析数据编码类型 的文章

 

随机推荐