swift网络请求 URLRequest

这篇博客介绍了在Swift中进行网络请求的步骤,包括创建`URLService`类来封装GET请求,处理URL字符串,以及设置请求超时时间。同时,提到了如何集成并使用MJRefresh库来实现UITableView的上下拉刷新功能,需要在桥接文件中导入MJRefresh并遵循相关协议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                             Swift网络请求数据

viewController中
import UIKit

class ViewController: UIViewController,UITableViewDataSource,MJRefreshBaseViewDelegate {

//表格属性
var table:UITableView?
var tableDataArr:[News]?

var mjHeaderView:MJRefreshHeaderView?
var mjFooterView:MJRefreshFooterView?

var startNum = 0

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    self.requestNetWorkDataAndUpdateUI()
}

//MARK: ------MJRefreshBaseViewDelegate ----------

func refreshViewBeginRefreshing(_ refreshView: MJRefreshBaseView!) {
    //如果是下拉,startNum值为0
    if refreshView is MJRefreshHeaderView {
        startNum = 0
    }else {
        startNum += 10
    }
    self.requestNetWorkDataAndUpdateUI()
}

//MARK: ------请求网络数据 ----------
func requestNetWorkDataAndUpdateUI() {
    //转动菊花
    UIApplication.shared.isNetworkActivityIndicatorVisible = true

    //请求网络数据

    let urlService = URLService()
    urlService.getNewsData(channel: "头条", startNum: self.startNum) { (data, success) in

        //先停止指示器
        DispatchQueue.main.sync {
            UIApplication.shared.isNetworkActivityIndicatorVisible = false
            //把下拉控件停止
            self.mjHeaderView?.endRefreshing()
            //把上拉控件停止
            self.mjFooterView?.endRefreshing()
        }

        if !success {
            DispatchQueue.main.async {
                let alertVC = UIAlertController(title: nil, message: data as?String, preferredStyle: .alert)
                let confirmBtn = UIAlertAction(title: "确定", style: .default, handler: nil)
                alertVC .addAction(confirmBtn)
                self.present(alertVC, animated: true, completion: nil)
            }
            return
        }

        //正确情况,加载表格
        //如果startNum是0,将第一页数据复制给数组
        if self.startNum == 0 {
            self.tableDataArr = data as? [News]
        }
        //如果不是0,将得到的数据拼接到上一页数据的后面
        else{
            let arr = data as? [News]
            self.tableDataArr?.append(contentsOf: arr!)
        }

        DispatchQueue.main.async(execute: { 
            self.table?.reloadData()
        })
    }

}

override func viewDidLoad() {
    super.viewDidLoad()

    self.table = UITableView(frame: self.view.frame, style: .plain)
    self.table?.dataSource = self
    self.view.addSubview(self.table!)

    //初始化下拉控件
    self.mjHeaderView = MJRefreshHeaderView(scrollView: self.table)
    self.mjHeaderView?.delegate = self
    //初始化上拉控件
    self.mjFooterView = MJRefreshFooterView(scrollView: self.table)
    self.mjFooterView?.delegate = self

}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if let count = tableDataArr?.count {
        return count
    }
    return 0
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let identifier = "cell"
    var cell = tableView.dequeueReusableCell(withIdentifier: identifier)
    if cell == nil {
        cell = UITableViewCell(style: .subtitle, reuseIdentifier: identifier)

    }
    let oneNew = self.tableDataArr![indexPath.row]

    cell?.textLabel?.text = oneNew.title
    cell?.detailTextLabel?.text = oneNew.content
    cell?.textLabel?.numberOfLines = 0

// cell?.detailTextLabel?.numberOfLines = 0

    return cell!
}

}

2.创建News文件
import UIKit

class News: NSObject {
var title = “”
var time = “”
var src = “”
var pic = “”
var content = “”
var url = “”
var weburl = “”
}
3.创建URLService.swift文件
import UIKit

class URLService: NSObject {
func getNewsData(channel:String,startNum:Int,completion:@escaping (Any,Bool) -> Void) {
//使用GET请求数据
//1.网址字符串拼接
var urlStr = “http://api.jisuapi.com/news/get?channel=(channel)&start=(startNum)&num=10&appkey=de394933e1a3e2db
//2.转码 (把中文转码)
urlStr = urlStr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlFragmentAllowed)!
//3.封装为URL对象
let url = URL(string: urlStr)
//4.封装为URLRequest对象(目的:设置请求超时时间)
let req = URLRequest(url: url!, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 15.0)

    //5.URLSession请求网络数据   //6.开启任务
    URLSession.shared.dataTask(with: req) { (data, response, error) in
        //如果发生错误
        if error != nil{
            //参数闭包的调用
            completion("网络服务器错误", false)
            return
        }
        //json数据解析
        let jsonData = try? JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments)

        //json解析失败 返回错误
        if jsonData == nil{
            completion("json解析错误",false)
            return
        }

        let status = (jsonData as! NSDictionary).value(forKey: "status") as! String

        let msg = (jsonData as! NSDictionary).value(forKey: "msg") as! String

        if Int(status)! != 0 {
            completion(msg, false)
            return
        }
        let result = (jsonData as! NSDictionary).value(forKey: "result") as! NSDictionary

        let list = result.value(forKey: "list") as! NSArray

        var newsArr:[News] = []
        for item in list{
            let dic = item as! NSDictionary

            let oneNew = News()
            oneNew.title = dic.value(forKey: "title") as! String
            oneNew.content = dic.value(forKey: "content") as! String
            oneNew.time = dic.value(forKey: "time") as! String
            oneNew.url = dic.value(forKey: "url") as! String
            oneNew.weburl = dic.value(forKey: "weburl") as! String
            newsArr.append(oneNew)
        }
        completion(newsArr, true)
    }.resume()
}

}

4.如果想要实现上下拉刷新,首先导入MJRefresh第三方文件夹,需要创建桥接文件,在桥接文件中导入#import “MJRefresh.h” 具体实现请参观以上代码注释

<think>好的,我现在需要回答用户在Swift中实现网络请求的问题,特别是关于教程和URLSession示例的。首先,我得回忆一下Swift网络请求的常见方法。用户提到了URLSession,这是苹果官方推荐的网络请求框架,所以应该从基础开始介绍。 首先,我应该解释URLSession的基本用法,比如创建URLSessionDataTask来处理GET请求。然后,可能需要提供一个简单的示例代码,展示如何发起请求并处理响应。用户可能对异步处理不太熟悉,所以需要提到回调的使用,以及数据解析的步骤,比如解析JSON。 接下来,用户提供的引用中有提到Get框架和Combine的dataTaskPublisher,这些是更高级的内容。虽然用户主要询问的是URLSession,但可能也需要简要提到这些库,供用户进一步学习参考。比如,引用[1]中的Get框架利用了Swift的async/await,这在Swift 5.5之后可用,可以提供更简洁的异步代码。而引用[2]中的Combine框架使用发布者模式来处理网络请求,适合响应式编程。 另外,用户引用[3]提到使用URLSession获取JSON数据,但可能不知道如何解析。所以,在示例中需要包含JSON解析的部分,或者至少引导用户查看相关解析的教程,比如提到的另一篇帖子。 在组织回答结构时,应该分步骤来,先讲基本用法,再展示代码示例,然后提到错误处理和常见问题。之后,可以补充高级方法,如async/await和Combine,这样用户可以根据自己的Swift版本和项目需求选择合适的方法。 需要确保代码示例正确,比如URLSession的使用步骤:创建URL对象,发起dataTask,处理响应数据,解析JSON,并在主线程更新UI。同时,要强调在回调中切换到主线程的必要性,避免UI更新问题。 另外,要检查是否有遗漏点,比如网络权限配置,iOS中需要在Info.plist中添加ATS例外或者使用HTTPS,但可能用户示例中使用的是HTTP,所以需要提醒。不过,可能用户只是需要一个简单示例,这部分可以在注意事项中提到。 最后,生成相关问题,帮助用户深入理解,比如如何优化请求、处理错误、使用第三方库等。这些问题应该基于回答中的内容,引导用户进一步探索。 总结一下,回答的结构应该是:介绍URLSession的基本用法,提供GET请求的代码示例,解析JSON,处理错误,然后介绍高级方法如async/await和Combine,最后给出注意事项和相关问题。确保引用标记正确,比如引用[1]、[2]、[3]在适当的位置。</think>### Swift中实现网络请求的逐步教程 #### 一、基础方法:URLSession实现GET请求 1. **创建URL对象** ```swift guard let url = URL(string: "https://api.example.com/data") else { print("无效URL") return } ``` 2. **创建URLSessionDataTask** ```swift let task = URLSession.shared.dataTask(with: url) { data, response, error in // 错误处理优先 if let error = error { print("请求失败: \(error.localizedDescription)") return } // 验证HTTP响应状态码 guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { print("服务端返回错误") return } // 数据解析 if let data = data { do { let json = try JSONSerialization.jsonObject(with: data) DispatchQueue.main.async { // 在主线程更新UI print("解析结果: \(json)") } } catch { print("JSON解析失败: \(error)") } } } task.resume() // 必须调用resume()启动任务 ``` #### 二、POST请求实现 ```swift var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") let postData = ["key": "value"] request.httpBody = try? JSONSerialization.data(withJSONObject: postData) URLSession.shared.dataTask(with: request) { data, _, _ in // 处理响应逻辑... }.resume() ``` #### 三、高级方法 1. **Swift 5.5+ 使用async/await** ```swift Task { do { let (data, response) = try await URLSession.shared.data(from: url) let decodedData = try JSONDecoder().decode(YourModel.self, from: data) } catch { print("请求失败: \(error)") } } ``` (该方法需要iOS 15+系统支持)[^1] 2. **Combine框架实现** ```swift URLSession.shared.dataTaskPublisher(for: url) .tryMap { output in guard let response = output.response as? HTTPURLResponse, response.statusCode == 200 else { throw URLError(.badServerResponse) } return output.data } .decode(type: YourModel.self, decoder: JSONDecoder()) .receive(on: DispatchQueue.main) .sink(receiveCompletion: { _ in }, receiveValue: { result in print("收到数据: \(result)") }) .store(in: &cancellables) ``` (需要导入Combine框架)[^2] #### 四、关键注意事项 1. **线程管理**:网络回调默认在后台线程,更新UI必须切到主线程 2. **错误处理**:必须处理三种错误类型: - 网络连接错误 - HTTP状态码错误(如404/500) - 数据解析错误 3. **HTTPS要求**:iOS默认强制ATS安全标准,如需使用HTTP需在Info.plist添加: ```xml <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict> ``` [^3] #### 五、推荐优化方案 1. 使用`URLSessionConfiguration`配置缓存策略: ```swift let config = URLSessionConfiguration.default config.requestCachePolicy = .returnCacheDataElseLoad let session = URLSession(configuration: config) ``` 2. 添加请求超时控制: ```swift request.timeoutInterval = 15 // 15秒超时 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值