協議://主機地址/路徑
。GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT
。狀態碼 | 描述 | 含義 |
---|---|---|
200 | Ok | 請求成功 |
400 | Bad Request | 客戶端請求的語法出現錯誤,服務端沒法解析 |
404 | Not Found | 服務端沒法根據客戶端的請求找到對應的資源 |
500 | Internal Server Error | 服務端內部出現問題,沒法完成響應 |
key : value
形式存在。,
分隔。{}
保存對象。[]
保存數組。""
。"
表示)[]
表示){}
表示)(1)URLSessionDataTask:請求數據的 Task。 (2)URLSessionUploadTask:上傳數據的 Task。 (3)URLSessionDownloadTask:下載數據的 Task。 6. 啓動任務。 7. 處理服務端響應,有 2 種方式。 (1)經過 completionHandler(閉包)處理服務端響應。 (2)經過 URLSessionDataDelegate(代理)處理請求與響應過程的事件和接收服務端返回的數據。javascript
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// get()
// post()
}
func get() {
// 1. 肯定URL
let url = URL(string: "http://v.juhe.cn/toutiao/index?type=top&key=申請的key")
// 2. 建立請求
let urlRequest = URLRequest(url: url!)
// cachePolicy: 緩存策略,App最經常使用的緩存策略是returnCacheDataElseLoad,表示先查看緩存數據,沒有緩存再請求
// timeoutInterval:超時時間
// let urlRequest = URLRequest(url: url!, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 5)
let config = URLSessionConfiguration.default
// 3. 建立URLSession
let session = URLSession(configuration: config)
// 4. 建立任務
let task = session.dataTask(with: urlRequest) { data, _, error in
if error != nil {
print(error!)
} else {
if let data = data {
print(String(data: data, encoding: .utf8)!)
}
}
}
// 5. 啓動任務
task.resume()
}
func post() {
let url = URL(string: "http://v.juhe.cn/toutiao/index")
var urlRequest = URLRequest(url: url!)
// 指明請求方法
urlRequest.httpMethod = "POST"
// 指明參數
let params = "type=top&key=申請的key"
// 設置請求體
urlRequest.httpBody = params.data(using: .utf8)
let config = URLSessionConfiguration.default
// delegateQueue決定了代理方法在哪一個線程中執行
let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue())
let task = session.dataTask(with: urlRequest)
task.resume()
}
}
// MARK:- URLSessionDataDelegate
extension ViewController: URLSessionDataDelegate {
// 開始接收數據
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
// 容許接收服務器的數據,默認狀況下請求以後不接收服務器的數據即不會調用後面獲取數據的代理方法
completionHandler(URLSession.ResponseDisposition.allow)
}
// 獲取數據
// 根據請求的數據量該方法可能會調用屢次,這樣data返回的就是總數據的一段,此時須要用一個全局的Data進行追加存儲
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
let result = String(data: data, encoding: .utf8)
if let result = result {
print(result)
}
}
// 獲取結束
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let error = error {
print(error)
} else {
print("=======成功=======")
}
}
}
複製代碼
注意:若是網絡請求是 HTTP 而非 HTTPS,默認狀況下,iOS 會阻斷該請求,此時須要在 Info.plist 中進行以下配置。html
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
複製代碼
let url = "https://www.baidu.com?name=張三"
.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
print(url) // URL中文轉碼
print(url.removingPercentEncoding!) // URL中文解碼
複製代碼
let str = "阿楚姑娘"
.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let url = URL(string: "https://music.163.com/#/search/m/?s=\(str)&type=1")
複製代碼
class ViewController: UIViewController {
// 下載進度
@IBOutlet var downloadProgress: UIProgressView!
// 下載圖片
@IBOutlet var downloadImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
download()
}
func download() {
let url = URL(string: "http://172.20.53.240:8080/AppTestAPI/wall.png")!
let request = URLRequest(url: url)
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue())
let task = session.downloadTask(with: request)
task.resume()
}
}
extension ViewController: URLSessionDownloadDelegate {
// 下載完成
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
// 存入沙盒
let savePath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
// 文件類型根據下載的內容決定
let fileName = "\(Int(Date().timeIntervalSince1970)).png"
let filePath = savePath + "/" + fileName
print(filePath)
do {
try FileManager.default.moveItem(at: location, to: URL(fileURLWithPath: filePath))
// 顯示到界面
DispatchQueue.main.async {
self.downloadImageView.image = UIImage(contentsOfFile: filePath)
}
} catch {
print(error)
}
}
// 計算進度
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
DispatchQueue.main.async {
self.downloadProgress.setProgress(Float(totalBytesWritten) / Float(totalBytesExpectedToWrite), animated: true)
}
}
}
複製代碼
上傳數據須要服務端配合,不一樣的服務端代碼可能會不同,下面的上傳代碼適用於本人所寫的服務端代碼。java
class ViewController: UIViewController {
let YFBoundary = "AnHuiWuHuYungFan"
@IBOutlet var uploadInfo: UILabel!
@IBOutlet var uploadProgress: UIProgressView!
override func viewDidLoad() {
super.viewDidLoad()
upload()
}
func upload() {
// 1. 肯定URL
let url = URL(string: "http://172.20.53.240:8080/AppTestAPI/UploadServlet")!
// 2. 肯定請求
var request = URLRequest(url: url)
// 3. 設置請求頭
let head = "multipart/form-data;boundary=\(YFBoundary)"
request.setValue(head, forHTTPHeaderField: "Content-Type")
// 4. 設置請求方式
request.httpMethod = "POST"
// 5. 建立NSURLSession
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue())
// 6. 獲取上傳的數據(按照固定格式拼接)
var data = Data()
let header = headerString(mimeType: "image/png", uploadFile: "wall.png")
data.append(header.data(using: .utf8)!)
data.append(uploadData())
let tailer = tailerString()
data.append(tailer.data(using: .utf8)!)
// 7. 建立上傳任務 上傳的數據來自getData方法
let task = session.uploadTask(with: request, from: data) { _, _, error in
// 上傳完畢後
if error != nil {
print(error!)
} else {
DispatchQueue.main.async {
self.uploadInfo.text = "上傳成功"
}
}
}
// 8. 執行上傳任務
task.resume()
}
// 開始標記
func headerString(mimeType: String, uploadFile: String) -> String {
var data = String()
// --Boundary\r\n
data.append("--" + YFBoundary + "\r\n")
// 文件參數名 Content-Disposition: form-data; name="myfile"; filename="wall.jpg"\r\n
data.append("Content-Disposition:form-data; name=\"myfile\";filename=\"\(uploadFile)\"\r\n")
// Content-Type 上傳文件的類型 MIME\r\n\r\n
data.append("Content-Type:\(mimeType)\r\n\r\n")
return data
}
// 結束標記
func tailerString() -> String {
// \r\n--Boundary--\r\n
return "\r\n--" + YFBoundary + "--\r\n"
}
func uploadData() -> Data {
let image = UIImage(named: "wall.png")
let imageData = image!.pngData()
return imageData!
}
}
extension ViewController: URLSessionTaskDelegate {
// 上傳進去
func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) {
DispatchQueue.main.async {
self.uploadProgress.setProgress(Float(totalBytesSent) / Float(totalBytesExpectedToSend), animated: true)
}
}
// 上傳出錯
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let error = error {
print(error)
}
}
}
複製代碼
URLCache.shared
獲取,也能夠自定義。// 建立URLCache
// memoryCapacity:內存緩存容量
// diskCapacity:硬盤緩存容量
// directory:硬盤緩存路徑
let cache = URLCache(memoryCapacity: 10 * 1024 * 1024, diskCapacity: 100 * 1024 * 1024, directory: FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first)
// 替換默認的緩存管理對象
URLCache.shared = cache
複製代碼
let url = URL(string: "http://v.juhe.cn/toutiao/index?type=top&key=申請的key")
let urlRequest = URLRequest(url: url!, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 5)
let cache = URLCache.shared
// 內存緩存大小
cache.memoryCapacity
// 硬盤緩存大小
cache.diskCapacity
// 已用內存緩存大小
cache.currentMemoryUsage
// 已用硬盤緩存大小
cache.currentDiskUsage
// 獲取某個請求的緩存
let cacheResponse = cache.cachedResponse(for: urlRequest)
// 刪除某個請求的緩存
cache.removeCachedResponse(for: urlRequest)
// 刪除某個時間點開始的緩存
cache.removeCachedResponses(since: Date().addingTimeInterval(-60 * 60 * 48))
// 刪除全部緩存
cache.removeAllCachedResponses()
複製代碼
WebKit
模塊。// 建立URL
let url = URL(string: "https://www.abc.edu.cn")
// 建立URLRequest
let request = URLRequest(url: url!)
// 建立WKWebView
let webView = WKWebView(frame: UIScreen.main.bounds)
// 加載網頁
webView.load(request)
複製代碼
// 文件夾路徑
let basePath = Bundle.main.path(forResource: "localWeb", ofType: nil)!
// 文件夾URL
let baseUrl = URL(fileURLWithPath: basePath, isDirectory: true)
// html路徑
let filePath = basePath + "/index.html"
// 轉成文件
let fileContent = try? NSString(contentsOfFile: filePath, encoding: String.Encoding.utf8.rawValue)
// 建立WKWebView
let webView = WKWebView(frame: UIScreen.main.bounds)
// 加載html
webView.loadHTMLString(fileContent! as String, baseURL: baseUrl)
複製代碼
注意:若是是本地資源是文件夾,拖進項目時,須要勾選
Create folder references
,而後用Bundle.main.path(forResource: "文件夾名", ofType: nil)
獲取資源路徑。web
lazy var webView: WKWebView = {
// 建立WKPreferences
let preferences = WKPreferences()
// 開啓JavaScript
preferences.javaScriptEnabled = true
// 建立WKWebViewConfiguration
let configuration = WKWebViewConfiguration()
// 設置WKWebViewConfiguration的WKPreferences
configuration.preferences = preferences
// 建立WKUserContentController
let userContentController = WKUserContentController()
// 配置WKWebViewConfiguration的WKUserContentController
configuration.userContentController = userContentController
// 給WKWebView與Swift交互起一個名字:callbackHandler,WKWebView給Swift發消息的時候會用到
// 此句要求實現WKScriptMessageHandler
configuration.userContentController.add(self, name: "callbackHandler")
// 建立WKWebView
var webView = WKWebView(frame: UIScreen.main.bounds, configuration: configuration)
// 讓WKWebView翻動有回彈效果
webView.scrollView.bounces = true
// 只容許WKWebView上下滾動
webView.scrollView.alwaysBounceVertical = true
// 設置代理WKNavigationDelegate
webView.navigationDelegate = self
// 返回
return webView
}()
複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0,user-scalable=no"/>
</head>
<body>
iOS傳過來的值:<span id="name"></span>
<button onclick="responseSwift()">響應iOS</button>
<script type="text/javascript"> // 給Swift調用 function sayHello(name) { document.getElementById("name").innerHTML = name return "Swift你也好!" } // 調用Swift方法 function responseSwift() { // 這裏的callbackHandler是建立WKWebViewConfiguration是定義的 window.webkit.messageHandlers.callbackHandler.postMessage("JavaScript發送消息給Swift") } </script>
</body>
</html>
複製代碼
// 加載完畢之後執行
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// 調用JavaScript方法
webView.evaluateJavaScript("sayHello('WebView你好!')") { (result, err) in
// result是JavaScript返回的值
print(result, err)
}
}
複製代碼
// Swift方法,能夠在JavaScript中調用
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
print(message.body)
}
複製代碼
class ViewController: UIViewController {
// 懶加載WKWebView
...
// 加載本地html
let html = try! String(contentsOfFile: Bundle.main.path(forResource: "index", ofType: "html")!, encoding: String.Encoding.utf8)
override func viewDidLoad() {
super.viewDidLoad()
// 標題
title = "WebView與JavaScript交互"
// 加載html
webView.loadHTMLString(html, baseURL: nil)
view.addSubview(webView)
}
}
// 遵照兩個協議
extension ViewController: WKNavigationDelegate, WKScriptMessageHandler {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
...
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
...
}
}
複製代碼
SafariServices
模塊。import SafariServices
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
showSafariViewController()
}
func showSafariViewController() {
// URL
let url = URL(string: "https://www.baidu.com")
// 建立SFSafariViewController
let sf = SFSafariViewController(url: url!)
// 設置代理
sf.delegate = self
// 顯示
present(sf, animated: true, completion: nil)
}
}
extension ViewController: SFSafariViewControllerDelegate {
// 點擊左上角的完成(done)
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
print(#function)
}
// 加載完成
func safariViewController(_ controller: SFSafariViewController, didCompleteInitialLoad didLoadSuccessfully: Bool) {
print(#function)
}
}
複製代碼