get和post区别
//get 速度快,不安全。 获取数据,传输少量的数据,不适合传输密码等隐私数据
//post 速度慢,相对安全。提交数据,传输大量数据,或隐私数据
虽然都可以用作登录请求,但是为了安全使用post
//1. 创建 设置 post请求
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http:xxxxxx/login.php"]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURl:url];
//设置post
request.HTTPMethod = @"post";
//设置请求体
NSString *bodyString = [NSString StringWithFormat:@"user"@"username=%@&password=%@",name,pwd]; //需要对pwd进行加密 ; 参照 原理笔记
request.HTTPbody = [bodyString dataUsingEncode:NSUTF8String]Encoding;
//2. 建立连接,发送请求....
登录成功后,把账号密码记录到沙盒的偏好设置和 钥匙串(第三方框架SSKeychain),
#define kUSERNAMEKEY @"HMUserName"
#define kUSERPWDKEY @"HMUserPwd"
//把用户信息保存到沙盒
- (void)saveUserInfo{
//用户偏好设置保存.
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setObject:self.nameView.text forKey:kUSERNAMEKEY];
//[userDefault setObject:self.pwdView.text forKey:kUSERPWDKEY]; // 为了安全 不保存密码到偏好设置.
//保存账号 和 密码到钥匙串.
[SSKeychain setPassword:self.pwdView.text forService:[NSBundle mainBundle].bundleIdentifier account:self.nameView.text];
//同步
[userDefault synchronize];
}
//从沙盒加载用户信息
- (void)loadUserInfo{
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
self.nameView.text = [userDefault objectForKey:kUSERNAMEKEY];
//从钥匙串读取密码
self.pwdView.text = [SSKeychain passwordForService:kBUNDLEID account:self.nameView.text];
}
扩展: 把异步登录的过程,封装成一个单例工具类;在appDelegate中实现自动登录;再使用回调的方式打开主控制器
在开发中,数据往往存储在服务器端,而客户端(iOS程序)往往通过向服务器发送请求从服务器获取数据.
而网络数据基本是以JSON形式传输;
一般步骤:
+ (void)newsWithSuccess:(void(^)(NSArray *array))success error:(void(^)())error {
//1 创建请求的地址
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
// url=[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];//有中文需要重新编码
//2. 创建请求
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 可以创建可变请求对象,从而设置 缓存策略cachePolicy 和 超时时间timeoutInterval 等
//3. 创建连接--向服务器发送请求,并接收服务器的响应
[NSURLConnection sendAsynchronousRequest:request queue:主队列 completionHandler:^(NSURLResponse *response,NSData *data,NSError * connectionError{//三个参数分别是服务器返回的响应, 数据, 错误信息;
if(!connectionError){
NSLog(@"连接错误%@",connectionError);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200 || httpResponse.statusCode == 304) {
//常用 JSON解析数据-反序列化-转模型 //假设这里JSON根节点是数组类型
NSArray *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
//遍历数组 转模型:
NSMutableArray *mArray = [NSMutableArray arrayWithCapacity:10];
[json enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
//模型内部 通过KVC给对象赋值
HMNews *news = [HMNews newsWithDic:obj]; //KVC注意条件
[mArray addObject:news];
}];
if (success){
success(mArray.copy) //block传值
} else {
NSLog(@"服务器内部错误")
if(error) { error(error);
}
}];
}
把解析过程封装到模型中,数据获取到之后回调数据; 控制器中跟以前一样不需变化.
之后控制器中调用此方法来获取数据
HMNews newsWithSuccess:^(NSArray *array) {
self.newsList = array;
} error:^(NSError *error){
NSLog(@"获取数据出错%@",error);
}];
注意:
现在多数情况下互联网数据都是以JSON格式进行传输,但是有时候也会面对XML存储。在IOS中可以使用NSXMLParser进行XML解析,由于实际使用并不多,在此不再赘述。
使用KVC给对象赋值时(通常是NSDictionary或NSMutalbeDictionary)注意对象的属性最好不要定义为基本类型(如int),否则如果属性值为null则会报错,最后定义为ObjC对象类型(如使用NSNumber代替int等);
开发web类的应用,图片缓存问题就不得不提及,因为图的下载相当耗时;在UItableView滚动就会重新加载数据,如果每次加载都从服务器端下载,那肯定不行;
解决方法有很多: 现存到内存,或存到临时文件,而存在内存虽然简单,但是并不可取,因为程序重新启动之后还要重新发送请求; 类似的微博,QQ等应用一般会存储在文件中,这样APP重启也能从文件中加载;但是使用此方法需要注意很多事:缓存文件是否过期,缓存数据越来越大如何管理存储空间等;
其实这些问题很多第三方框架都做得很好,我们基本都是用第三方框架来解决SDWebImage/YYkit;
[_mbType sd_setImageWithURL:mbTypeUrl ];
在上面的方法中直接调用了SDWebImage的分类缓存方法设置图片,这个方法可以分配另外一个线程去加载图片(同时对于头像还指定了默认图片,网速较慢时不至于显示空白),图片加载后存放在沙箱的缓存文件夹;
滚动UITableView再次加载同一个图片时SDWebImage就会自动判断缓存文件是否有效,如果有效就加载缓存文件,否则重新加载。
文件上传必须采用POST上传,同时请求头Content-Type类型必须是multipart/form-data。数据在HTTPbody里面上传,必须遵守格式;
//创建请求
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request= [NSMutableURLRequest requestWithURL:url];
//设置请求
request.HTTPMethod=@"POST";
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",kBOUNDARY] forHTTPHeaderField:@"Content-Type"]; //kBOUNDARY-签名自拟.
request.HTTPBody = [self makeBody:fieldName filePath:filePath];
设置请求上传内容格式
- (NSData *)makeBody:(NSString *)fieldName filePath:(NSString *)filePath {
NSMutableData *mData = [NSMutableData data];
//第一部分
NSMutableString *mString = [NSMutableString string];
[mString appendFormat:@"--%@\r\n",kBOUNDARY];
[mString appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",fieldName,[filePath lastPathComponent]];
[mString appendString:@"Content-Type: application/octet-stream\r\n"];
[mString appendString:@"\r\n"];
//
[mData appendData:[mString dataUsingEncoding:NSUTF8StringEncoding]];
//第二部分 //加载文件
NSData *data = [NSData dataWithContentsOfFile:filePath];
[mData appendData:data];
//第三部分
NSString *end = [NSString stringWithFormat:@"\r\n--%@--",kBOUNDARY];
[mData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];
return mData.copy;
}
上传多个文件按以下格式
按照如下格式 转换成NSdata;
--分隔符\r\n
这个文件的请求头\r\n
\r\n
文件数据\r\n
--分隔符\r\n
这个文件的请求头\r\n
\r\n
文件数据\r\n
--分隔符--
return NSData.copy
}
注意:上传文件时,有时希望传递一些附加信息给服务器;使用JSON形式字符串,即JSON序列化;