暑假第三周任务——天气预报
文章目录
- 暑假第三周任务——天气预报
- 前言
- URL与API
- API与URL的关系
- 获取网络请求
- 首页
- 搜索界面
- 详情界面
- 添加功能
- 浏览界面
- 总结
前言
这个天气预报主要是通过申请网络请求来获取实时数据,来实现一个天气预报的功能,在这里主要是因为笔者第一次接触有关通过网络请求来获取数据的相关内容,所以刚开始遇到很多问题,后面渐渐的才找回一点思路去完成这个项目
URL与API
这里概念笔者引自其他人的博客API介绍
API(Application Programming Interface)是一些预先定义的函数,或指软件系统不同组成部分衔接的约定。也可以理解为是两个应用程序之间通信的机制,或者使用一组规则和协议的组件或计算机硬件。
URL(uniform resource locator;URL)是因特网的万维网服务程序上用于指定信息位置的表示方法。
API与URL的关系
- Web API 是通过 URL 暴露的。每个 Web API 的端点(Endpoint)都有一个对应的 URL。
- URL作为API的访问接口,我们可以通过特定的URL来调用API的功能。
简单来说就是
URL 是一个定位符,标识资源的位置和访问方式。
API 是一组接口,定义了如何访问和使用某些功能或数据。
Web API 使用 URL 作为其访问点,客户端通过 URL 发送请求来调用 API 的功能。
获取网络请求
在简单了解这两者的区别之后,我们现在要学习如何获取网络请求,主要也就分成了
首先我们要学会怎么获取网络请求。
一共分成五个步骤:
- 创建请求地址
- 创建请求类
- 创建会话
- 根据会话创建任务
- 启动任务
注意这里需要遵循协议NSURLSessionDelegate
,下面给出相关代码
//创建请求地址,笔者这里是传入了一个城市的一个strId,这样才可以构成一个完整的请求地址。
NSString* urlString = [NSString stringWithFormat: @"https://geoapi.qweather.com/v2/city/lookup?location=%@&key=2211750bdc834763ba3c5f57ce98c307", self.search.text];
NSURL *url = [NSURL URLWithString:urlString];
//创建请求类
NSURLRequest* request = [NSURLRequest requestWithURL:url];//通过URL创建一个网络请求类
//创建会话
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//根据会话创建任务。
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"error = %@", error.localizedDescription);
} else {
[self.locationArray removeAllObjects];
NSDictionary* second = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSMutableArray* timeAry = [[NSMutableArray alloc] init];
timeAry = second[@"location"];
//NSLog(@"%@", timeAry);
NSLog(@"geo");
for (NSDictionary* current in timeAry) {
[self.locationArray addObject:current];
}
}
}];
//启动任务
[dataTask resume];
这里解释一下上面几个函数的相关用法
sessionWithConfiguration:delegate:delegateQueue:
这是一个类方法,用于创建一个 NSURLSession 实例。
configuration: NSURLSessionConfiguration 对象,定义了会话的行为、策略和超时等属性。这里使用的是 [NSURLSessionConfiguration defaultSessionConfiguration],表示使用默认的会话配置。
delegate: 指定会话的委托对象。委托对象会实现 NSURLSessionDelegate 协议,用于处理会话相关的事件。
delegateQueue: 指定一个 NSOperationQueue,用于调度委托方法的执行。这里使用的是 [NSOperationQueue mainQueue],表示委托方法将在主线程上执行。
这里的第五步其实可以采用一个 [session dataTaskWithURL:url completionHandler:]
的方式去创建一个,但是如果以后面的方式去创建的话,就意味着是以一种GET方式去获取网络请求,这样只能满足一些简单的网络请求,而使用request方式来获取数据可以满足更复杂的情况。
所以我们尽量采用request方法来获取网络请求,采用request的方式可以满足更多需求
首页
这里我先给出首页的一个效果,我在这里只是简单的在导航栏上面加了一个searchBar的控件,然后设置了一个左侧的导航栏的一个Label。初始化界面设计了一个北京作为起初就存在的一个cell,这里有部分设置圆角cell的内容,但对于这部分内容,笔者也只是粗略了解了一席通过贝塞尔曲线来绘制一个圆角cell的内容。
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat radius = 10;
if ([tableView numberOfRowsInSection:indexPath.section] == 1) {//判断每组cell的一个行数。
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:cell.bounds cornerRadius:radius];// 使用指定的圆角半径radius创建一个带有圆角的矩形路径
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];//CAShapeLayer 是一个图层类。它的主要作用是将 UIBezierPath 描绘的路径应用到图层上。
maskLayer.frame = cell.bounds;//设置frame
maskLayer.path = maskPath.CGPath;//设置对应路径
cell.layer.mask = maskLayer;//完成覆盖,只有被覆盖的位置会被遮盖
}
}
剩下的内容都是通过类似的网络请求来获取相关的一个数据,然后加载到cell上。
搜索界面
这里我们先给出一个效果图。
可以看到我们这里实现了一个通过添加字符实时搜索的一个效果,这就是我们需要实现的模糊搜索的效果。这里主要要注意的是我们对于搜索时候刷新UITableVIew的一个时机,这里笔者使用的是UISearchBar这个控件,这里我们需要使用一个协议方法来实现一个模糊搜索。
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(nonnull NSString *)searchText
这个协议函数是实时监控我输入文字的变化的,每次输入完我们只要进行一次网络请求,就可以实现一个模糊搜索的效果。
详情界面
这里详情页主要的功能就是展示我们该城市的一个天气,这里同样是通过一个UITableVIew和其他UITableVIew的一个嵌套实现一个我们需要的一个效果,笔者这里使用的是和风天气的图标:和风天气,也是使用这个API来调用我们所需要的一个数据内容。
添加功能
这里我们的详情页要有一个添加到首页的功能,这里我使用的是一个通知传值,我通过通知中心来给前两个页面传值,将这个城市的Id传回去,然后在通知传值的接受方法里面,在原先的数组里面添加,然后刷新单元格就可以实现这个效果,这里还存在一个判重的问题,这里的判重,我是通过传入的城市id数组通过一个for循环遍历来判别重复
浏览界面
这里浏览界面其实是通过一个视图控制器控制多个子视图控制器,并且将这些子视图控制器的view添加到主视图控制器的滑动视图上面,这样就可以实现一个轮播图的效果
这里我给出相关代码
for (int i = 0; i < count; i++) {
detailViewController* deatil = [[detailViewController alloc] init];
deatil.addButton.hidden = YES;
deatil.strId = self.nameAry[i];
NSLog(@"%@", deatil.strId);
deatil.tag = i;
deatil.nameArray = [self.nameAry mutableCopy];
deatil.iconArray = [self.timeAry mutableCopy];
deatil.view.frame = CGRectMake(WIDTH * i, 0, WIDTH, HEIGHT);
UIButton* btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(10, 10, 60, 60);
[btn setTitle:@"返回" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(press) forControlEvents:UIControlEventTouchUpInside];
[self addChildViewController:deatil];//给自己添加子视图控制器
[self.scrollView addSubview:deatil.view];//给滑动视图添加我们子视图控制器的view
[deatil.tableView addSubview:btn];
}
总结
这是暑假最后一个任务,第一次学习有关网络请求的内容,刚开始确实会不从下手,但是多写写相关代码,多看看相关的博客,才可以找到相关的思路,要多去尝试,才可以完成一个项目。