首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

iOS 入門級網絡請求:NSURLSession 異步加載網頁完整示例

     編輯:關於C語言

最簡單的「請求-響應-渲染」閉環

本文提供一個零依賴、可直接運行的 iOS 網絡請求範例,涵蓋 URL 構建、異步會話、數據解碼、主線程 UI 更新全流程。

完整代碼

// ViewController.m
#import "ViewController.h"

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

#pragma mark - 點擊屏幕發起請求
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"測試");
    [self test];
}

- (void)test {
    // 1. 統一資源定位符
    NSURL *url = [NSURL URLWithString:@"https://www.baidu.com"];

    // 2. 創建請求對象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    // 3. 發送異步請求(NSURLSession 默認異步,無同步 API)
    // completionHandler 在後台線程執行
    [[[NSURLSession sharedSession] dataTaskWithRequest:request
        completionHandler:^(NSData * _Nullable data,
                            NSURLResponse * _Nullable response,
                            NSError * _Nullable error) {

            // 4. 二進制數據轉字符串
            NSString *html = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

            // 5. 切回主線程更新 UI
            dispatch_async(dispatch_get_main_queue(), ^{
                // 6. 創建 WebView 載入 HTML
                UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
                [webView loadHTMLString:html baseURL:url];
                [self.view addSubview:webView];

                /* 
                替代方案:
                [webView loadData:data MIMEType:nil textEncodingName:nil baseURL:url];
                [webView loadRequest:request]; // 直接加載請求
                */

                // 7. 可選:保存 HTML 到沙盒
                // [data writeToFile:@"路徑/文件.html" atomically:YES];
            });

        }] resume]; // 必須調用 resume 啟動任務
}

@end

流程圖解

用戶點擊
    ↓
NSURL (統一資源定位)
    ↓
NSMutableURLRequest (可變請求,可加 Header/Body)
    ↓
NSURLSession.sharedSession (單例會話)
    ↓
dataTaskWithRequest (數據任務)
    ↓
resume() 啟動
    ↓
--- 後台線程 ---
completionHandler(data, response, error)
    ↓
NSData → NSString (UTF-8 解碼)
    ↓
dispatch_async(main_queue) 切主線程
    ↓
UIWebView 初始化 + loadHTMLString
    ↓
addSubview 顯示

關鍵概念釐清

為什麼網絡請求必須異步?

網絡 I/O 屬於耗時操作,若在主線程同步阻塞會導致界面卡頓甚至觸發 Watchdog 崩潰(0x8badf00d)。iOS 強制網絡 API 異步化。

NSURLSession 線程模型

  • 創建任務:主線程
  • resume:立即返回,底層開啟網絡連接
  • completionHandler:**默認在後台串行隊列**執行(非主線程)
  • Delegate 方法:若使用 Delegate 模式,回調線程取決於 delegateQueue(默認主隊列)

UIWebView vs WKWebView 選擇

UIWebViewWKWebView
狀態iOS 12 棄用,App Store 可能拒審推薦,持續維護
進程App 進程內(佔用 App 內存)獨立進程(內存隔離,崩潰不影響 App)
性能較差接近 Safari,JS 引擎快
API簡單功能豐富(導航代理、腳本注入等)

常見坑點

  1. 忘記 resume():任務創建後處於掛起狀態,必須調用 resume 才會發送請求。
  2. HTTP 明文傳輸被 ATS 攔截:iOS 9+ 預設阻止非 HTTPS 請求。需在 Info.plist 配置 NSAppTransportSecurity 允許 HTTP 或特定域名。
  3. 子線程更新 UI:導致佈局錯亂、崩潰或警告。永遠 dispatch_async(main_queue)。
  4. 編碼錯誤:頁面非 UTF-8 時 initWithData:encoding: 返回 nil。可嘗試 CFStringConvertEncodingToNSStringEncoding 檢測編碼。

進階擴展

  • 錯誤處理:判斷 error 與 response.statusCode
  • 超時設置:request.timeoutInterval = 15;
  • 緩存策略:request.cachePolicy = NSURLRequestUseProtocolCachePolicy;
  • 大文件下載:改用 downloadTask 支持斷點續傳
  • 第三方庫:AFNetworking (OC) / Alamofire (Swift) 封裝更友好
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved