上个月实在是太忙了,在系统上线的前几天,业务人员还在不停的提新需求,真是醉了。上线那天晚上一直在出问题,熬到2点才搞定
2015/12/12
Day 47
今天开始学习网络编程
UIWebView
■ UIWebView是iOS内置的浏览器控件,可以浏览网页、打开文档等
■ 能够加载html/htm、pdf、docx、txt等格式的文件
■ 系统自带的Safari浏览器就是通过UIWebView实现的
UIWebView演练——加载百度首页
很简单,只要调用UIWebView的loadRequest方法即可,如下,
- (void)viewDidLoad { [super viewDidLoad]; [self loadURL:@"http://www.baidu.com"]; } - (void)loadURL:(NSString *)str { [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:str]]]; }
值得一提的是,现在需要在info.plist中设置使用http请求
第一步:在plist中添加NSAppTransportSecurity项,此项为NSDictionary
第二步:在NSAppTransportSecurity下添加
NSAllowsArbitraryLoads类型为Boolean,value为YES
苹果正在加大应用安全的管控,这个举措可以看出苹果对信息安全的重视,也暴露出大部分应用传输数据时都是未经过加密的,或使用私有方式加密,以至于苹果开始对开发者提出要求。
私有加密虽然一定程度上是安全的,但是终究不是一个长久之计。应该早日使用HTTPS确保信息安全!
NSURL 确定要访问的网络资源
NSURLRequest 建立网络请求
然后配置本地服务器
通过命令行直接可以使用诸如:C、C++、Python、Ruby、PHP、JavaScript、Perl等语言进行开发,Mac是程序员开发的利器
Mac系统中上很多程序员使用的工具和软件都是通过命令行实现的,例如:Apache、SQLite、音频格式转换、视频格式转换、SVN、GIT……
判断本地计算机的Apache服务器是否启动
在浏览器地址栏中输入:localhost
通过是否有返回结果,即可判断本地的Apache是否正常工作
然后更改配置文件让服务器支持php
在Mac中,如果要执行系统级命令,或者修改系统级文件,需要通过sudo命令来执行。需要先输入管理员口令才可以执行需要的命令
■ 启动
sudo apachectl -k start
■ 重新启动
sudo apachectl -k restart
PHP简介
然后安装mysql
2015/12/13
Day 48
昨天把服务器和数据库都配置好了
今天学习 get&post请求
先在数据库建表
drop table if exists userInfo;
create table userInfo (
id mediumint not null auto_increment primary key,
userName varchar(255) not null default '',
userPwd varchar(255) not null default '',
sex tinyint not null default 0,
userImage varchar(255) not null default '',
location varchar(255) not null default '',
description varchar(255) not null default '',
birthday varchar(255) not null default '',
email varchar(255) not null default '',
blog varchar(255) not null default '',
qq varchar(255) not null default '',
msn varchar(255) not null default ''
);
insert into userInfo (userName, userPwd) values ('yu3', '123456');
insert into userInfo (userName, userPwd) values ('zhangsan', 'zhang');
insert into userInfo (userName, userPwd) values ('lisi', 'li');
insert into userInfo (userName, userPwd) values ('wangwu', 'wang');
然后利用php发送请求,login.php内容如下
<?php class users { private $db; //构造函数 - 建立数据库连接 function __construct() { $this->db = new mysqli('127.0.0.1', 'root', '123456', 'yu3'); if (mysqli_connect_errno()) { printf("连接错误:%s\n", mysqli_connect_error()); exit(); } $this->db->autocommit(FALSE); } //析构函数 - 关闭数据库连接 function __destruct() { $this->db->close(); } //用户登录 function userLogin() { if (isset($_GET['username']) && isset($_GET['password'])) { //获取参数 $accessType = '[GET]'; $userName = $_GET['username']; $userPassword = $_GET['password']; } else if (isset($_POST['username']) && isset($_POST['password'])) { //获取参数 $accessType = '[POST]'; $userName = $_POST['username']; $userPassword = $_POST['password']; } else { echo('非法请求。'); return false; } //设置数据库查询字符编码 $this->db->query('set names utf8'); //查询请求 $data = $this->db->query("select id, userName, sex from userInfo where userName='$userName' and userPwd='$userPassword'"); //绑定查询参数 $this->db->real_escape_string($userName); $this->db->real_escape_string($userPassword); //提交查询请求 $this->db->commit(); //提取查询结果 $row = $data->fetch_assoc(); //将查询结果绑定到字典 $result = [ 'userId' => $row['id'], 'userName' => $row['userName'], 'sex' => $row['sex'] ]; //将字典使用JSON编码 echo json_encode($result); return true; } } header('Content-Type:text/html;charset=utf-8'); $users = new users; $users->userLogin(); ?>
这样在浏览器中发送请求如下,根据zhangsan密码zhang可以查出表里的数据
简历工程,在storyboard里,设置两个textField输入用户名密码,然后点击按钮放松请求,接收的数据在textView里显示
先发送get请求
NSLog(@"GET请求开始 %@",[NSThread currentThread]); NSString *urlStr = [NSString stringWithFormat:@"http://localhost/login.php?username=%@&password=%@", self.userName.text, self.pwd.text]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]]; NSLog(@"GET请求-NSURLRequest:%@ %@", request, [NSThread currentThread]); // Connection // 1> 登录完成之前,不能做后续工作! // 2> 登录进行中,可以允许用户干点别的会更好! // 3> 让登录操作在其他线程中进行,就不会阻塞主线程的工作 // 4> 结论:登陆也是异步访问,中间需要阻塞住 [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { if (connectionError == nil) { NSLog(@"response:%@ %@",response, [NSThread currentThread]); NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"返回的字符串:%@ - %@", str, [NSThread currentThread]); [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.responseText.text = str; NSLog(@“GET请求-更新UI %@",[NSThread currentThread]); }]; } NSLog(@"GET请求结束 %@", [NSThread currentThread]); }]; NSLog(@"GET请求-主线程其他工作 %@", [NSThread currentThread]);
然后是post请求
NSLog(@"POST请求开始 %@",[NSThread currentThread]); NSString *urlStr = @"http://localhost/login.php"; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlStr]]; //设置请求类型为POST request.HTTPMethod = @"POST"; NSString *str = [NSString stringWithFormat:@"username=%@&password=%@", self.userName.text, self.pwd.text]; request.HTTPBody = [str dataUsingEncoding:NSUTF8StringEncoding]; NSLog(@"POST请求-NSMutableURLRequest:%@ %@", request, [NSThread currentThread]); [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) { if (connectionError == nil) { NSLog(@"response:%@ %@",response, [NSThread currentThread]); NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"返回的字符串:%@ - %@", str, [NSThread currentThread]); [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.responseText.text = str; NSLog(@"更新UI %@",[NSThread currentThread]); }]; } NSLog(@"POST请求结束 %@", [NSThread currentThread]); }]; NSLog(@"POST请求-主线程其他工作 %@", [NSThread currentThread]);
ios9.0以后苹果建议我们使用NSURLSession
NSURLConnection 作为 Core Foundation / CFNetwork 框架的 API 之上的一个抽象,在 2003 年,随着第一版的 Safari 的发布就发布了。NSURLConnection 这个名字,实际上是指代的 Foundation 框架的 URL 加载系统中一系列有关联的组件:NSURLRequest、NSURLResponse、NSURLProtocol、 NSURLCache、 NSHTTPCookieStorage、NSURLCredentialStorage 以及同名类 NSURLConnection。
NSURLRequest 被传递给 NSURLConnection。被委托对象(遵守以前的非正式协议 <NSURLConnectionDelegate> 和<NSURLConnectionDataDelegate>)异步地返回一个 NSURLResponse 以及包含服务器返回信息的 NSData。
在一个请求被发送到服务器之前,系统会先查询共享的缓存信息,然后根据策略(policy)以及可用性(availability)的不同,一个已经被缓存的响应可能会被立即返回。如果没有缓存的响应可用,则这个请求将根据我们指定的策略来缓存它的响应以便将来的请求可以使用。
在把请求发送给服务器的过程中,服务器可能会发出鉴权查询(authentication challenge),这可以由共享的 cookie 或机密存储(credential storage)来自动响应,或者由被委托对象来响应。发送中的请求也可以被注册的 NSURLProtocol 对象所拦截,以便在必要的时候无缝地改变其加载行为。
不管怎样,NSURLConnection 作为网络基础架构,已经服务了成千上万的 iOS 和 Mac OS 程序,并且做的还算相当不错。但是这些年,一些用例——尤其是在 iPhone 和 iPad 上面——已经对 NSURLConnection 的几个核心概念提出了挑战,让苹果有理由对它进行重构。
在 2013 的 WWDC 上,苹果推出了 NSURLConnection 的继任者:NSURLSession。
和 NSURLConnection 一样,NSURLSession 指的也不仅是同名类 NSURLSession,还包括一系列相互关联的类。NSURLSession 包括了与之前相同的组件,NSURLRequest 与 NSURLCache,但是把 NSURLConnection 替换成了NSURLSession、NSURLSessionConfiguration 以及 NSURLSessionTask 的 3 个子类:NSURLSessionDataTask,NSURLSessionUploadTask,NSURLSessionDownloadTask。
与 NSURLConnection 相比,NSURLsession 最直接的改进就是可以配置每个 session 的缓存,协议,cookie,以及证书策略(credential policy),甚至跨程序共享这些信息。这将允许程序和网络基础框架之间相互独立,不会发生干扰。每个NSURLSession 对象都由一个 NSURLSessionConfiguration 对象来进行初始化,后者指定了刚才提到的那些策略以及一些用来增强移动设备上性能的新选项。
NSURLSession 中另一大块就是 session task。它负责处理数据的加载以及文件和数据在客户端与服务端之间的上传和下载。NSURLSessionTask 与 NSURLConnection 最大的相似之处在于它也负责数据的加载,最大的不同之处在于所有的 task 共享其创造者 NSURLSession 这一公共委托者(common delegate)。
我们先来深入探讨 task,过后再来讨论 NSURLSessionConfiguration。
NSURLSessionTask
NSURLSessionTask is an abstract subclass, with three concrete subclasses that are used directly:NSURLSessionDataTask, NSURLSessionUploadTask, and NSURLSessionDownloadTask. These three classes encapsulate the three essential networking tasks of modern applications: fetching data, such as JSON or XML, and uploading and downloading files.
NSURLsessionTask 是一个抽象类,其下有 3 个实体子类可以直接使用:NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask。这 3 个子类封装了现代程序三个最基本的网络任务:获取数据,比如 JSON 或者 XML,上传文件和下载文件。
当一个 NSURLSessionDataTask 完成时,它会带有相关联的数据,而一个 NSURLSessionDownloadTask 任务结束时,它会带回已下载文件的一个临时的文件路径。因为一般来说,服务端对于一个上传任务的响应也会有相关数据返回,所以NSURLSessionUploadTask 继承自 NSURLSessionDataTask。
所有的 task 都是可以取消,暂停或者恢复的。当一个 download task 取消时,可以通过选项来创建一个恢复数据(resume data),然后可以传递给下一次新创建的 download task,以便继续之前的下载。
不同于直接使用 alloc-init 初始化方法,task 是由一个 NSURLSession 创建的。每个 task 的构造方法都对应有或者没有completionHandler 这个 block 的两个版本,例如:有这样两个构造方法 –dataTaskWithRequest: 和 –dataTaskWithRequest:completionHandler:。这与 NSURLConnection 的 -sendAsynchronousRequest:queue:completionHandler: 方法类似,通过指定 completionHandler 这个 block 将创建一个隐式的 delegate,来替代该 task 原来的 delegate——session。对于需要 override 原有 session task 的 delegate 的默认行为的情况,我们需要使用这种不带 completionHandler 的版本。
下面是用NSURLSession重构代码,GET请求
NSLog(@"GET请求开始 %@",[NSThread currentThread]); NSString *urlStr = [NSString stringWithFormat:@"http://localhost/login.php?username=%@&password=%@", self.userName.text, self.pwd.text]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]]; NSLog(@"GET请求-NSURLRequest:%@ %@", request, [NSThread currentThread]); //构造Session NSURLSession *session = [NSURLSession sharedSession]; NSLog(@"GET请求-NSURLSession:%@ %@",session, [NSThread currentThread]); NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:urlStr] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error == nil) { NSLog(@"GET请求-NSURLResponse:%@ %@",response, [NSThread currentThread]); NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"GET请求-返回的字符串:%@ - %@", str, [NSThread currentThread]); [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.responseText.text = str; NSLog(@"GET请求-更新UI %@",[NSThread currentThread]); }]; } NSLog(@"GET请求结束 %@", [NSThread currentThread]); }]; NSLog(@"GET请求-NSURLSessionDataTask:%@ %@",task, [NSThread currentThread]); [task resume]; NSLog(@"GET请求-主线程其他工作 %@", [NSThread currentThread]);
控制台打印如下
然后是POST请求,代码如下
NSLog(@"POST请求开始 %@",[NSThread currentThread]); NSString *urlStr = @"http://localhost/login.php"; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlStr]]; //设置请求类型为POST request.HTTPMethod = @"POST"; NSString *str = [NSString stringWithFormat:@"username=%@&password=%@", self.userName.text, self.pwd.text]; request.HTTPBody = [str dataUsingEncoding:NSUTF8StringEncoding]; NSLog(@"POST请求-NSMutableURLRequest:%@ %@", request, [NSThread currentThread]); //构造Session NSURLSession *session = [NSURLSession sharedSession]; NSLog(@"POST请求-NSURLSession:%@ %@",session, [NSThread currentThread]); NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error == nil) { NSLog(@"POST请求-NSURLResponse:%@ %@",response, [NSThread currentThread]); NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"POST请求-返回的字符串:%@ - %@", str, [NSThread currentThread]); [[NSOperationQueue mainQueue] addOperationWithBlock:^{ self.responseText.text = str; NSLog(@"POST请求-更新UI %@",[NSThread currentThread]); }]; } NSLog(@"POST请求结束 %@", [NSThread currentThread]); }]; NSLog(@"POST请求-NSURLSessionDataTask:%@ %@",task, [NSThread currentThread]); [task resume]; NSLog(@"POST请求-主线程其他工作 %@", [NSThread currentThread]);
下面是控制台打印
下面是swift版的代码,GET请求
print("GET请求-开始-\(NSThread.currentThread())") let urlStr = "http://localhost/login.php?username=\(self.userName.text!)&password=\(self.pwd.text!)" let request = NSURLRequest(URL: NSURL(string: urlStr)!) print("GET请求-request:\(request)-\(NSThread.currentThread())") let session = NSURLSession.sharedSession() let task = session.dataTaskWithURL(NSURL(string: urlStr)!) { (responseData, response, error) -> Void in if error == nil { print("GET请求-response:\(response)-\(NSThread.currentThread())") let str = NSString(data: responseData!, encoding: NSUTF8StringEncoding)! print("GET请求-返回字符串:\(str)-\(NSThread.currentThread())") NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in self.responseText.text = String(str) print("GET请求-更新UI-\(NSThread.currentThread())") }) } } task.resume() print("GET请求-主线程其他工作-\(NSThread.currentThread())")
控制台打印如下
POST请求,代码如下
print("POST请求-开始-\(NSThread.currentThread())") let urlStr = "http://localhost/login.php" //设置request let request = NSMutableURLRequest(URL: NSURL(string: urlStr)!) request.HTTPMethod = "POST" let str = "username=\(self.userName.text!)&password=\(self.pwd.text!)" request.HTTPBody = str.dataUsingEncoding(NSUTF8StringEncoding) print("POST请求-request:\(request)-\(NSThread.currentThread())") let session = NSURLSession.sharedSession() let task = session.dataTaskWithRequest(request) { (responseData, response, error) -> Void in if error == nil { print("POST请求-response:\(response)-\(NSThread.currentThread())") let str = NSString(data: responseData!, encoding: NSUTF8StringEncoding)! print("POST请求-返回字符串:\(str)-\(NSThread.currentThread())") NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in self.responseText.text = String(str) print("POST请求-更新UI-\(NSThread.currentThread())") }) } } task.resume() print("POST请求-主线程其他工作-\(NSThread.currentThread())")
控制台打印
2016/01/08
Day 48
今天学习JSON与XML解析,我对这两种数据格式都有所了解,学起来还是很简单的
JSON的序列化和反序列化
[NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
[NSJSONSerialization dataWithJSONObject:array options:0 error:NULL];
NSJSONReadingOptions
如果枚举类型的起始数值是1,通常0就表示什么选项也不支持,是效率最高的选项
NSXMLParser解析方法
NSXMLParser解析过程
实例化NSXMLParser,传入从服务器接收的XML数据
定义解析器代理
解析器解析
通过解析代理方法完成XML数据的解析
NSXMLParser解析代理方法
// 1. 开始解析XML文档
- (void)parserDidStartDocument:
// 2. 开始解析某个元素,会遍历整个XML,识别元素节点名称
- (void)parser:didStartElement:namespaceURI:qualifiedName:attributes:
// 3. 文本节点,得到文本节点里存储的信息数据,对于大数据可能会接收多次!为了节约内存开销
- (void)parser:foundCharacters:
// 4. 结束某个节点,存储从parser:foundCharacters:方法中获取到的信息
- (void)parser:didEndElement:namespaceURI:qualifiedName:
注意:在解析过程中,2、3、4三个方法会不停的重复执行,直到遍历完成为止
// 5. 解析XML文档结束
- (void)parserDidEndDocument:
// 6. 解析出错
- (void)parser:parseErrorOccurred: