本文将演示如果通过Get的方式,请求某地天气信息,同步获取网络数据,
一旦发送同步请求,程序将停止用户交互,直至服务器返回数据。
为了增强数据访问的安全性,从9.0版本开始,Xcode默认会把所有的网络请求,修改为https安全请求。
也可以修改配置文件,以支持普通的网络请求。
点击打开【Info.plist】属性列表文件。
在配置文件编辑区的空白处,点击鼠标右键,弹出功能菜单。
->【Add Row】
->【Information Property List】在键列表中选择需要设置的键【App Transport Security Settings】
->点击键左侧的右向箭头,显示所属的选项。
->点击键右侧的【+】添加一个子属性。
->在键名输入框内选择【Allow Arbitrary Loads】选择允许加载非安全请求的属性名称。
->点击子属性的值,更改布尔值为真Yes。
在项目导航区,打开视图控制器的代码文件【ViewController.swift】
1 import UIKit 2 3 class ViewController: UIViewController { 4 5 //给当前视图控制器类,添加一个标签属性。 6 //该标签对象,将用来显示远程服务器返回的信息 7 var label = UILabel() 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 // Do any additional setup after loading the view, typically from a nib. 12 13 //设置标签对象的位置在(20,40),尺寸为(280,500) 14 label.frame = CGRect(x: 20, y: 40, 280, height: 500) 15 //设置标签对象的文字内容 16 label.text = "Loading..." 17 //设置标签对象的字体和大小 18 label.font = UIFont(name: "Arial", size: 12) 19 //设置标签对象的背景颜色为浅灰色 20 label.backgroundColor = UIColor.lightGray 21 //设置标签对象的行数属性值为0,表示不限制标签对象的行数。 22 label.numberOfLines = 0 23 //远程服务器有可能返回较多的文字内容, 24 //在此设置标签对象在进行换行时,保留所有的字符 25 label.lineBreakMode = NSLineBreakMode.byWordWrapping 26 //将设置好的标签对象,添加到当前视图控制器的根视图 27 self.view.addSubview(label) 28 29 //创建一个网址对象,指定请求网络数据的网址。 30 //网址最后面的一串数字,表示某地区的编号,此处代表北京地区 31 let url = URL(string: "http://www.weather.com.cn/data/sk/101010100.html") 32 33 //创建一个网络请求对象,参数说明: 34 //1.代表请求访问的路径 35 //2.代表网络请求的缓存协议 36 //3.代表网络请求的超时时间 37 let request = URLRequest.init(url:url!, //1.代表请求访问的路径 38 cachePolicy: NSURLRequest.CachePolicy.useProtocolCachePolicy, //2.代表网络请求的缓存协议 39 timeoutInterval: 30)//3.代表网络请求的超时时间 40 41 //初始化一个信号量,它是一种用来控制并发访问资源的机制, 42 //常用于多线程中,可以控制并发线程的数量。 43 //这里设置信号量为0,使线程一直等待,从而产生同步请求的效果。 44 let semaphore = DispatchSemaphore(value: 0) 45 46 //网址会话URLSession在2013年发布,苹果对它的定位是作为旧的网络请求接口的替代者。 47 //这里获得网址会话的单例对象 48 let session = URLSession.shared 49 //所有网络请求工作,都是通过网址会话任务对象来完成的。 50 //可以使用闭包、代理或者两者混合的方式,来创建网络请求任务。 51 let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in 52 //如果出现网络请求错误, 53 if error != nil{ 54 //则在控制台打印输出错误代码和错误信息 55 print(error.debugDescription) 56 }else{ 57 //将网络返回的数据对象,根据指定的编码方式,转换为字符串 58 let result = String(data: data!, encoding: String.Encoding.utf8) 59 //然后返回主线程, 60 DispatchQueue.main.async(execute: { () -> Void in 61 //更新标签对象的文字内容 62 //界面元素的刷新,需要在主线程进行 63 self.label.text = result! as String 64 }) 65 } 66 67 //将信号量进行发送,使信号量加1, 68 //此时其他等待中的线程就会被唤醒, 69 //从而完成同步网络请求的操作 70 semaphore.signal() 71 }) 72 73 //任务创建后,调用resume方法开始工作。 74 task.resume() 75 76 //等待信号量,timeout参数可以控制等待的最长时间,distantFuture表示永久等待 77 _ = semaphore.wait(timeout: DispatchTime.distantFuture) 78 //在网络的同步请求结束之后,在控制台输出日志信息 79 print("数据加载完毕!") 80 } 81 82 override func didReceiveMemoryWarning() { 83 super.didReceiveMemoryWarning() 84 // Dispose of any resources that can be recreated. 85 } 86 }