IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> iPhone开发Swift基础03 视频、网络请求 -> 正文阅读

[移动开发]iPhone开发Swift基础03 视频、网络请求

视频播放AVPlayer

iOS9之前使用的是MPMoviePlayerController,随着iOS不断迭代,AVPlayer成为主流。
往项目中添加资源文件:
添加资源

import UIKit
import AVFoundation

class ViewController: UIViewController{
    var avPlayer : AVPlayer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let mp4url = Bundle.main.path(forResource: "apple", ofType: "mp4")
        let movieURL = URL(fileURLWithPath: mp4url!)
        avPlayer = AVPlayer(url: movieURL)
        
        let avPlayerLayer = AVPlayerLayer(player: avPlayer)
        avPlayerLayer.frame = self.view.frame
        avPlayerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
        self.view.layer.addSublayer(avPlayerLayer)
        
        avPlayer?.play()
    }
}

videoGravity属性类型:

  • AVLayerVideoGravity.resizeAspectFill 保留宽高比,填满屏幕
  • AVLayerVideoGravity.resizeAspect 显示范围内缩放视频大小,保持宽高比
  • AVLayerVideoGravity.resize 拉伸视频来匹配显示区域

AVPlayerViewController

使用AVPlayerViewController需要再import AVKit

import UIKit
import AVFoundation
import AVKit

class ViewController: UIViewController{
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let mp4url = Bundle.main.path(forResource: "apple", ofType: "mp4")
        let movieURL = URL(fileURLWithPath: mp4url!)
        
        let avPlayer = AVPlayer(url: movieURL)
        let avPlayerVC = AVPlayerViewController()
        avPlayerVC.player = avPlayer
        avPlayerVC.videoGravity = AVLayerVideoGravity.resizeAspect
        avPlayerVC.allowsPictureInPicturePlayback = true
        avPlayerVC.showsPlaybackControls = true
        avPlayerVC.view.frame = self.view.bounds
        
        avPlayerVC.player!.play()
        self.view.addSubview(avPlayerVC.view)
    }
}

配置画中画

项目配置画中画的过程

  • 第一步点击Capabilities
  • 第二步点击增加Capabilities - Background Modes
  • 第三步点击Audio AirPlay and Picture in Picture

网络请求

HTTP定义了与服务器交互的不同方法,其中最基本的有4种:GET、POST、PUT、DELETE。

GET与POST

每个GET与POST都由一系列的HTTP请求头组成,这些请求头定义了客户端想从服务器端请求什么数据。同样,响应是由一系列的应答头和应答数据组成。

GET使用MIME类型application/x-www-form-urlencoded的urlencoded文本格式传递参数。Urlencoding是一种字符编码,保证被传递的参数遵循规范。

POST参数也是被URL编码的,但变量名/变量值不作为URL的一部分被传送,而是放在实际HTTP请求消息内部被传送。

GET是从服务器上获取数据,POST是向服务器发送数据。GET通过URL提交数据,数据可以在URL中看见。POST是将请求数据放在请求头HTML HEADER 内提交的。GET提交的数据最多只能有1024字节,而POST没有这个限制。使用GET的时候,参数会暴露出来而POST不会,因此,GET常用于提交非敏感数据。

在iOS开发中常用URLSession的委托协议来实现不同阶段回调不同的对象方法。

URLSession

使用URLSession进行网络请求

URLSession是一组相互依赖的类,它的绝大部分组件和NSURLConnection中的组件相同。比如,URLRequest、URLCache等等。

URLSession的不同之处在于,它将URLConnection替换为URLSession和URLSessionConfiguration,以及三个URLSessionTask的子类:URLSessionDataTask、URLSessionUploadTask、URLSessionDownloadTask。

使用URLSession可以实现:

  • 通过URL下载数据到内存
  • 通过URL下载数据到文件系统
  • 将数据上传到指定的URL
  • 在后台完成上传和下载
  • 下载文件具有断点续传的功能
  • 后台上传或下载具有任务进度跟踪的功能
class ViewController: UIViewController{
    
    var label : UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        label = UILabel(frame: CGRect(x: 0, y: 0, width: 480, height: 568))
        label.text = "loading..."
        label.font = UIFont(name: "Arial", size: 14)
        label.numberOfLines = 0
        label.lineBreakMode = NSLineBreakMode.byWordWrapping
        self.view.addSubview(label)
        
        let urlString:String = "https://www.baidu.com"
        let url:URL!=URL(string: urlString)
        
        let request:URLRequest = URLRequest(url: url)
        let session = URLSession.shared
        
        let dataTask = session.dataTask(with: request) { (data, response, error) in
            print("有结果了")
            if error != nil {
                print(error?.localizedDescription)
            }else{
                //因为URLSession请求是异步进行的,
                //所以需要返回主线程更新UI
                DispatchQueue.main.async {
                    let str = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
                    self.label.text = str as! String
                }
            }
        }
        
        dataTask.resume()
    }
}

运行结果:
在这里插入图片描述
let dataTask = session.dataTask(with: request) { (data, response, error) 这一段,只不过是session单例对象声明处理执行的url并在完成后调用尾部闭包的处理的一个过程。但实际上并没有开始执行网络请求,在调用resume()后才开始执行请求任务。

除了请求远程数据以外,URLSession还有上传和下载的功能。使用该功能需要遵循URLSessionDownloadDelegate协议来实现下载进度的监听。

class ViewController: UIViewController, URLSessionDownloadDelegate{
    var backgroundView:UIView!
    var foregroundView:UIView!
    var progressLabel:UILabel!
    
    //初始化URLSession对象,并设置代理为当前的控制器,由控制器实现代理方法来监听图片下载
    func getSession() -> Foundation.URLSession {
        var session:URLSession? = nil
        let config = URLSessionConfiguration.default
        session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
        return session!
    }
    
    //监听图片下载完成的代理方法
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        print("下载完成!")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        backgroundView = UIView(frame: CGRect(x: 50, y: 50, width: 200, height: 40))
        backgroundView.backgroundColor = UIColor.lightGray
        
        foregroundView = UIView(frame: CGRect(x: 54, y: 54, width: 0, height: 32))
        foregroundView.backgroundColor = UIColor.green
        
        progressLabel = UILabel(frame: CGRect(x: 54, y: 100, width: 200, height: 32))
        progressLabel.textAlignment = NSTextAlignment.center
        
        self.view.addSubview(backgroundView)
        self.view.addSubview(foregroundView)
        self.view.addSubview(progressLabel)
        
        let urlString:String = "https://p8.itc.cn/images01/20210416/0f44703fd5754c24af70ea031fe135b4.png"
        let url:URL!=URL(string: urlString)
        let request:URLRequest = URLRequest(url: url)
        let session = self.getSession() as Foundation.URLSession
        let downloadTask = session.downloadTask(with: request)
        downloadTask.resume()
    }
    
    //监听下载进度的代理方法
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        let rate:CGFloat = CGFloat(totalBytesWritten)/CGFloat(totalBytesExpectedToWrite)
        DispatchQueue.main.async {
            self.foregroundView.frame.size.width = rate * 192
            if rate == 1.0 {
                self.progressLabel.text = "Finished."
            }
        }
    }
}

运行结果:
在这里插入图片描述

Alamofire

在OC时代,Alamofire的名字是AFNetworking。

使用Alamofire进行GET请求

在使用前需要先import Alamofire 框架。

Alamofire的使用方式较4.0版本有了较大的不同,比如4.0时期用Alamofire调用类方法的,现在5.0使用AF。

而且在返回值方面也做了较明显的改动。自己阅读,这里给出请求范例

import UIKit
import Alamofire

class ViewController: UIViewController{
    
    override func viewDidLoad() {
        super.viewDidLoad()
        getInfo()
    }
    
    func getInfo() -> () {
        let url : String = "https://www.baidu.com/get"
        AF.request(url).responseString { (afDataResponseString) in
            print(afDataResponseString)
        }
    }
}

运行结果:

success("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>404 Not Found</title>\n</head><body>\n<h1>Not Found</h1>\n<p>The requested URL /get was not found on this server.</p>\n</body></html>\n")

Alamofire默认是进行GET请求。Alamofire最大的特色就是采用链式请求/响应的方式来进行网络交互,如上述代码所示,请求request与返回体respond都写在一行上。代码量非常少、简洁。

使用Alamofire进行POST请求
import UIKit
import Alamofire

class ViewController: UIViewController{
    
    override func viewDidLoad() {
        super.viewDidLoad()
        postInfo()
    }
    
    func postInfo() -> () {
        //声明post的参数类型为键值对都是String的字典类型
        var parameters : Dictionary<String,String> = Dictionary()
        parameters["email"] = "fzhlee@coolketang.com"
        parameters["password"] = "123456"
        let url : String = "https://www.coolketang.com/post"
        
        struct DecodableType: Decodable { let url: String }
        AF.request(url, method: HTTPMethod.post, parameters: parameters, encoding: URLEncoding.default, headers: nil, interceptor: nil, requestModifier: nil).responseDecodable(of: DecodableType.self) { (dataResponse) in
            print("\(dataResponse)")
        }
        
        AF.request(url, method: HTTPMethod.post, parameters: parameters, encoding: URLEncoding.default, headers: nil, interceptor: nil, requestModifier: nil).responseString { (dataResponse) in
            print("\(dataResponse)")
        }
    }
}

运行结果:
结果无法确认
由于学习的这本教材所支持的服务器已经没有提供相应的反应,无法确认,以后有其他的网站示例再更新吧。

使用Alamofire上传图片

当使用JSON或URL编码参数向服务器发送较少数据的时候,Alamofire的request方法是够用的,但是面对上传图片或者其他大文件的时候就需要用到Alamofire的upload方法了。

首先往项目中导入示例资源文件wind.png
导入示例资源文件

import UIKit
import Alamofire

class ViewController: UIViewController{
    
    override func viewDidLoad() {
        super.viewDidLoad()
        uploadImage()
    }
    
    func uploadImage() -> () {
        let imageURL = Bundle.main.url(forResource: "wind", withExtension: "png")
        
        struct DecodableType: Decodable { let url: String }
        AF.upload(imageURL!, to: "https://httpbin.org/post").uploadProgress { (progress) in
            print("--进度:\(progress.fractionCompleted)")
            print("--完成:\(progress.completedUnitCount)")
            print("--总量:\(progress.totalUnitCount)")
        }.responseDecodable { (dataResponse:DataResponse<DecodableType, AFError>) in
            let message = "Result:\(dataResponse.result)"
            print(message)
        }
    }
}

在upload方法中,其第一个参数也可以是Data数据类型,这样就可以将内存中的数据上传到服务器中。

另外在Alamofire请求数据的过程中会收集每个步骤的耗时,并生成一个时间线对象

运行结果:

--进度:0.11106045996139592
--完成:65536
--总量:590093
--进度:1.0
--完成:590093
--总量:590093
Result:success(S1.ViewController.(unknown context at $106e70ce8).(unknown context at $106e70d3c).DecodableType(url: "https://httpbin.org/post"))

在返回体dataResponse中,通过断点逐个查看其中的成员属性,还有一些关于请求、加载、解析等耗时的统计。

AlamofireImage

使用AlamofireImage缓存图片

Alamofire还有一些扩展,AlamofireImage就是其中之一,能够处理图像处理和缓存等方面的拓展。

使用AlamofireImage来进行加载图片时,具有以下特点:

  • 使用简单,自动在内存中缓存图片,加载过的图片在没有网络的时候也能显示。
  • 包含一些常用的扩展,如压缩、缩放、圆角、滤镜等等。

在使用之前先导入框架,以CocoaPods的方式:
导入

import UIKit
import Alamofire
import AlamofireImage

class ViewController: UIViewController{
    var imageView : UIImageView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        getImageByAlamofireImage()
    }
    
    func getImageByAlamofireImage() -> () {
        let image = UIImage(named: "wind.png")!
        let imageSize = CGSize(width: 100, height: 100)
        
        //使用AlamofireImage处理图像
        let scaleImage = image.af.imageScaled(to: imageSize)
        
        //用图片去初始化imageview,这样imageView的尺寸就会是图片的尺寸
        imageView = UIImageView(image: scaleImage)
        imageView?.center = self.view.center
        self.view.addSubview(imageView!)
    }
}

运行结果:
在这里插入图片描述

使用AlamofireImage给图片添加滤镜
//使用AlamofireImage处理图像
let blurImage = image.af.imageFiltered(withCoreImageFilter: "CIMotionBlur", parameters: ["inputRadius":5,"inputAngle":45])
imageView = UIImageView(image: blurImage)
imageView?.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
imageView?.center = self.view.center

运行结果;
毛玻璃效果

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-12-26 22:18:57  更:2021-12-26 22:20:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:00:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码