前言
近期寫完了暑假最后一個任務(wù)——天氣預(yù)報,在里面用到了簡單的網(wǎng)絡(luò)數(shù)據(jù)請求以及json數(shù)據(jù)的解析,特此記錄博客總結(jié)
一、json數(shù)據(jù)解析
JSON是一種輕量級的數(shù)據(jù)格式,一般用于數(shù)據(jù)交互。目前JSON的使用非常廣泛,絕大多數(shù)網(wǎng)絡(luò)請求都采用了JSON格式。
舉個例子:
{
"code": "200",
"updateTime": "2021-11-15T16:35+08:00",
"fxLink": "http://hfx.link/2ax1",
"daily": [
{
"fxDate": "2021-11-15",
"sunrise": "06:58",
"sunset": "16:59",
"moonrise": "15:16",
"moonset": "03:40",
"moonPhase": "盈凸月",
"moonPhaseIcon": "803",
"tempMax": "12",
"tempMin": "-1",
"iconDay": "101",
"textDay": "多云",
"iconNight": "150",
"textNight": "晴",
},
{
"fxDate": "2021-11-16",
"sunrise": "07:00",
"sunset": "16:58",
"moonrise": "15:38",
"moonset": "04:40",
"moonPhase": "盈凸月",
"moonPhaseIcon": "803",
"tempMax": "13",
"tempMin": "0",
"iconDay": "100",
"textDay": "晴",
"iconNight": "101",
"textNight": "多云",
}
],
"refer": {
"sources": [
"QWeather",
"NMC",
"ECMWF"
],
"license": [
"QWeather Developers License"
]
}
}
這就是我們利用API請求到的json數(shù)據(jù),接下來我們對其進(jìn)行解釋
JSON的格式很像Objective-C中的字典和數(shù)組,標(biāo)準(zhǔn)JSON格式key必須用雙引號包裹起來。像上述數(shù)據(jù)中的code,updateTime都是字典中的key。我們用一張圖來解釋我們的json數(shù)據(jù):
例如在上面的json數(shù)據(jù)中,daily就相當(dāng)于我們的NSArray,數(shù)組中的每一個元素的類型都是NSDictionary(字典)。
搞清楚json數(shù)據(jù)中每個數(shù)據(jù)的類型后,我們就要去得到對應(yīng)的數(shù)據(jù),具體怎么得到將會在下文講解完簡單的網(wǎng)絡(luò)數(shù)據(jù)請求后一并解釋,在此我們只需要知道json數(shù)據(jù)在OC中對應(yīng)的數(shù)據(jù)類型即可
二、簡單的網(wǎng)絡(luò)數(shù)據(jù)請求
在學(xué)習(xí)網(wǎng)絡(luò)數(shù)據(jù)請求之前,我們有必要先了解兩個概念:URL和API
API(應(yīng)用程序編程接口)和URL(統(tǒng)一資源定位器)之間有密切的關(guān)系,但它們代表了不同的概念。
URL是用于定位資源在網(wǎng)絡(luò)上的地址,它描述了資源的位置和訪問方式。在Web中,URL通常用于標(biāo)識和定位網(wǎng)頁、圖片、視頻或其他文件。一個標(biāo)準(zhǔn)的URL通常由協(xié)議(例如HTTP或HTTPS)、主機(jī)名(例如www.example.com)、可選的端口號、文件路徑和查詢參數(shù)組成。例如:https://www.example.com/api/get_data。
API是一組規(guī)定的規(guī)則和協(xié)議,用于不同軟件應(yīng)用程序之間的通信和交互。API定義了應(yīng)用程序如何請求和交換信息。在Web開發(fā)中,API通常以URL的形式提供,通過HTTP請求發(fā)送給服務(wù)器,并以JSON或XML等格式返回數(shù)據(jù)。API允許開發(fā)人員訪問遠(yuǎn)程服務(wù)的功能或數(shù)據(jù),而不需要了解底層的實現(xiàn)細(xì)節(jié)。
因此,URL可以被視為API的一部分。URL是實現(xiàn)訪問API的重要組成部分,它是指向API的網(wǎng)絡(luò)地址,用于標(biāo)識和定位API的特定功能和資源。通過構(gòu)建和發(fā)送HTTP請求到API的URL,可以實現(xiàn)與API的交互,請求數(shù)據(jù)或執(zhí)行操作。
API一般是通過URL的形式進(jìn)行訪問,API相當(dāng)于一種接口,而URL則是我們訪問相應(yīng)API所必須的參數(shù)
接下來筆者簡單講解一下iOS進(jìn)行簡單的網(wǎng)絡(luò)數(shù)據(jù)請求的六步:
- 創(chuàng)建API的URL:構(gòu)建API的URL,包括指定基本地址、路徑和查詢參數(shù)等。
- 創(chuàng)建一個NSURL對象:使用URL字符串來創(chuàng)建NSURL對象,以便在請求中使用。
- 創(chuàng)建NSURLRequest:使用NSURL對象創(chuàng)建一個NSURLRequest對象,該對象將包含請求的類型(GET、POST等)和其他必要的信息。
- 創(chuàng)建NSURLSession:初始化NSURLSession來管理網(wǎng)絡(luò)會話,它是發(fā)送請求的主要組件。
- 創(chuàng)建NSURLSessionDataTask:使用NSURLSession創(chuàng)建一個NSURLSessionDataTask對象,用于發(fā)送網(wǎng)絡(luò)請求,并在請求完成后接收數(shù)據(jù)。
- 處理請求結(jié)果:在請求完成后,處理服務(wù)器返回的數(shù)據(jù)并進(jìn)行相應(yīng)的處理,例如解析數(shù)據(jù)或更新UI。
// 引入頭文件
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 1. 創(chuàng)建API的URL
NSString *urlString = @"https://api.example.com/data"; // 請?zhí)鎿Q為實際的API地址
// 2. 創(chuàng)建NSURL對象
NSURL *url = [NSURL URLWithString:urlString];
// 3. 創(chuàng)建NSURLRequest
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 4. 創(chuàng)建NSURLSession
NSURLSession *session = [NSURLSession sharedSession];
// 5. 創(chuàng)建NSURLSessionDataTask
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
// 處理請求出錯
NSLog(@"Error: %@", error.localizedDescription);
} else {
// 6. 處理請求結(jié)果(這里簡單地將返回的數(shù)據(jù)轉(zhuǎn)為字符串并輸出)
NSString *responseData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Response: %@", responseData);
// 如果需要解析JSON數(shù)據(jù),可以使用NSJSONSerialization類進(jìn)行解析
// NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
}
}];
// 7. 啟動數(shù)據(jù)任務(wù)
[dataTask resume];
}
@end
需要注意的是這里只是最簡單的GET請求,后續(xù)還會有POST請求等知識,筆者以后學(xué)到再進(jìn)行補(bǔ)充
同時我們注意我們的第四步的方法也可以用+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;
這個方法來實現(xiàn),其與[NSURLSession sharedSession]
方法的區(qū)別在于后者只能用于簡單的網(wǎng)絡(luò)請求,而前者可以允許您使用自定義配置來創(chuàng)建會話,并且可以設(shè)置代理來處理相關(guān)事件
假設(shè)我們的API需要進(jìn)行HTTP基本認(rèn)證(Basic Authentication),我們需要在請求中包含用戶名和密碼。在這種情況下,我們可以在 NSURLSessionDelegate 中實現(xiàn)URLSession:task:didReceiveChallenge:completionHandler:
方法來處理認(rèn)證。
#import "ViewController.h"
@interface ViewController () <NSURLSessionDelegate>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 1. 創(chuàng)建API的URL
NSString *urlString = @"https://api.example.com/data"; // 請?zhí)鎿Q為實際的API地址
// 2. 創(chuàng)建NSURL對象
NSURL *url = [NSURL URLWithString:urlString];
// 3. 創(chuàng)建NSURLSessionConfiguration
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
// 4. 創(chuàng)建NSURLSession并設(shè)置代理
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
// 5. 創(chuàng)建NSURLSessionDataTask
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
// 處理請求出錯
NSLog(@"Error: %@", error.localizedDescription);
} else {
// 處理請求結(jié)果(這里簡單地將返回的數(shù)據(jù)轉(zhuǎn)為字符串并輸出)
NSString *responseData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Response: %@", responseData);
}
}];
// 6. 啟動數(shù)據(jù)任務(wù)
[dataTask resume];
}
#pragma mark - NSURLSessionDelegate
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler {
// 這里我們處理HTTP基本認(rèn)證(Basic Authentication)
if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]) {
// 在這里設(shè)置您的用戶名和密碼
NSString *username = @"your_username";
NSString *password = @"your_password";
// 創(chuàng)建NSURLCredential對象
NSURLCredential *credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistenceForSession];
// 調(diào)用完成處理程序,將憑據(jù)傳遞給會話
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
}
}
@end
同樣的,在第五步中,我們同樣可以使用兩種方法來進(jìn)行我們的數(shù)據(jù)請求
dataTaskWithRequest:completionHandler: 方法需要您自己創(chuàng)建和配置一個 NSURLRequest 對象,然后將其作為參數(shù)傳遞給該方法,以實現(xiàn)更多自定義和配置的選項。
dataTaskWithURL:completionHandler: 方法更為簡潔,只需要傳遞一個 NSURL 對象,即請求的目標(biāo)URL,而不需要自己創(chuàng)建和配置 NSURLRequest 對象。這個方法是發(fā)送GET請求的快捷方式,適用于簡單的數(shù)據(jù)獲取。
但是在實際代碼中我們更推薦使用第一種方法進(jìn)行請求,因為我們的POST與GET一般結(jié)合在一起使用,也許GET方法可以不用到Request,但是POST方法一定會用到,這里的講解等后面學(xué)到了具體寫博客進(jìn)行講解,這里給出POST的栗子:
- (void)sendPOSTRequest {
// 1. 創(chuàng)建API的URL
NSString *urlString = @"https://api.example.com/post_endpoint"; // 請?zhí)鎿Q為實際的POST請求的URL
// 2. 創(chuàng)建NSURL對象
NSURL *url = [NSURL URLWithString:urlString];
// 3. 創(chuàng)建NSMutableURLRequest對象,并設(shè)置HTTP方法為POST
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
// 4. 如果有需要,設(shè)置HTTP請求頭,例如Content-Type等
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
// 5. 如果有參數(shù)或需要發(fā)送數(shù)據(jù),可以將其添加到HTTP請求體中
NSDictionary *parameters = @{@"key1": @"value1", @"key2": @"value2"};
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:&error];
if (!error) {
[request setHTTPBody:postData];
} else {
NSLog(@"Error creating POST data: %@", error.localizedDescription);
return;
}
// 6. 創(chuàng)建NSURLSession,并發(fā)送POST請求
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
// 處理請求出錯
NSLog(@"Error: %@", error.localizedDescription);
} else {
// 處理請求結(jié)果
NSString *responseData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Response: %@", responseData);
}
}];
// 7. 啟動數(shù)據(jù)任務(wù)
[dataTask resume];
}
三、實現(xiàn)訪問API得到網(wǎng)絡(luò)數(shù)據(jù)
講解完我們的基本的網(wǎng)絡(luò)數(shù)據(jù)請求的步驟,我們以我們上面的以我們上面的json數(shù)據(jù)為例來進(jìn)行一個簡單的網(wǎng)絡(luò)數(shù)據(jù)請求:
{
"code": "200",
"updateTime": "2021-11-15T16:35+08:00",
"fxLink": "http://hfx.link/2ax1",
"daily": [
{
"fxDate": "2021-11-15",
"sunrise": "06:58",
"sunset": "16:59",
"moonrise": "15:16",
"moonset": "03:40",
"moonPhase": "盈凸月",
"moonPhaseIcon": "803",
"tempMax": "12",
"tempMin": "-1",
"iconDay": "101",
"textDay": "多云",
"iconNight": "150",
"textNight": "晴",
},
{
"fxDate": "2021-11-16",
"sunrise": "07:00",
"sunset": "16:58",
"moonrise": "15:38",
"moonset": "04:40",
"moonPhase": "盈凸月",
"moonPhaseIcon": "803",
"tempMax": "13",
"tempMin": "0",
"iconDay": "100",
"textDay": "晴",
"iconNight": "101",
"textNight": "多云",
}
],
"refer": {
"sources": [
"QWeather",
"NMC",
"ECMWF"
],
"license": [
"QWeather Developers License"
]
}
}
例如我們想要的到j(luò)son數(shù)據(jù)中的fxDate,首先我們需要使用+ (nullable id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
將我們的訪問API得到的二進(jìn)制數(shù)據(jù) data 解析為 NSDictionary 對象(或 NSArray 對象)。根據(jù)上面的知識我們可以知道我們需要將其解析為NSDictionary。于是我們使用如下代碼先來解析我們的整個json數(shù)據(jù) NSDictionary *weatherData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
然后我們可以知道我們字典中對應(yīng)的“daily”鍵的類型實際上是一個NSArray對象,我們要想得到fxDate,首先需要訪問daily,于是我們用如下代碼得到daily NSArray *dailyArray = weatherData[@"daily"];
由于我們的daily數(shù)組中的每個對象類型都NSDictionary,于是我們可以使用如下代碼得到我們數(shù)組中所有的fxDate
for (NSDictionary *currentDayData in dailyArray) {
NSString *timeString = currentDayData[@"fxDate"]; // 時間
NSLog(@"%@", timeString);
}
得到我們?nèi)缦碌慕Y(jié)果:
給出完整代碼供大家參考:
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
// 請求出錯處理
} else {
NSDictionary *weatherData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if (error) {
// 解析數(shù)據(jù)出錯處理
} else {
// 解析數(shù)據(jù)成功
NSArray *dailyArray = weatherData[@"daily"];
for (NSDictionary *currentDayData in dailyArray) {
NSString *timeString = currentDayData[@"fxDate"]; // 時間
NSLog(@"%@", timeString);
}
NSLog(@"無法獲取當(dāng)前時間的天氣數(shù)據(jù)。");
}
}
}
}];
總結(jié)
筆者在這里簡單了講解了一下基本的網(wǎng)絡(luò)數(shù)據(jù)請求,實際上隨著iOS的發(fā)展出現(xiàn)了許多第三方庫例如JSONModel等,可以讓我們更加方便的解析json以及請求網(wǎng)絡(luò)數(shù)據(jù),另外還有網(wǎng)絡(luò)數(shù)據(jù)請求的POST用法筆者還不甚了解,后面學(xué)到會一并總結(jié)文章來源:http://www.zghlxwxcb.cn/news/detail-623075.html
json數(shù)據(jù)來源:
和風(fēng)每日天氣文章來源地址http://www.zghlxwxcb.cn/news/detail-623075.html
到了這里,關(guān)于【iOS】json數(shù)據(jù)解析以及簡單的網(wǎng)絡(luò)數(shù)據(jù)請求的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!