这周的任务是天气预报的仿写,用到了网络请求
网络请求
API
API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
暂且把它粗浅的理解成别人编译好的程序,拿过来可以直接用
做天气的网络请求首先要搞到一个好用的天气API,这样根据请求到的数据放到解析网站解析之后,就可以清晰直观的得到一个字典来使用,如下:
如何请求到数据
代码放上:
//这里传入城市中文名称的NSString,应对不同的城市名称
- (void)requestNewCity:(NSString*) city {
//请求 URL
NSString* urlStr = [NSString stringWithFormat:@"https://v0.yiketianqi.com/api/worldchina?appid=52318441&appsecret=DHC2a3sA&city=%@",city];
NSLog(@"%@", urlStr);
//处理字符串(将中文转换等)
urlStr = [urlStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//封装成 NSURL
NSURL *url = [NSURL URLWithString:urlStr];
NSLog(@"%@", url);
//初始化 请求对象
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
//也可以这样初始化对象
//NSURLRequest* request = [NSURLRequest requestWithURL:url];
//或者写为如下形式
//NSMutableURLRequest *requestSecond = [NSMutableURLRequest initWithURL:url];
//[requestSecond setHTTPMethod:@"GET"];
//发送请求 默认为 GET 请求
//1 、获得会话对象
NSURLSession *session = [NSURLSession sharedSession];
// 2、第一个参数:请求对象
// 第二个参数:completionHandler回调(请求完成【成功|失败】的回调)
// data:响应体信息(期望的数据)
// response:响应头信息,主要是对服务器端的描述
// error:错误信息,如果请求失败,则error有值
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if(!error){
NSLog(@"请求加载成功。。。");
//说明:(此处返回的数据是JSON格式的,因此使用NSJSONSerialization进行反序列化处理)
NSLog(@"%@", data);
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(@"%@", dict);
NSString *country = [dict valueForKey:@"country"];
//主线程操作
//由于目前阶段我不知道怎么处理异步,通过请教学长,得到这样一个回到主线程操作,继续完成UI部分
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
//在私有的ViewController的可变字典属性上,进行属性传值,把字典传到这个ViewController类里。
self.dictInAddView = [[NSMutableDictionary alloc]initWithDictionary:dict];
OneDetailViewController* newController = [[OneDetailViewController alloc]init];
//此时我的newController得到了网络请求来的信息字典
newController.dict = [[NSMutableDictionary alloc]initWithDictionary:dict];
newController.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:newController animated:YES completion:nil];
}];
//验证申请成功与否
NSLog(@"%@", country);
} else {
NSLog(@"网络请求失败!");
}
}];
//执行任务
[dataTask resume];
}
提供API的网址是这个:
15日天气 逐小时天气
UI思路
搜索界面
这里在向搜索框输入字符时,也是调用了网络申请的,会自动弹出与字符相关联的城市。
cell的点击事件,弹出所选中的城市的天气概览,上方左右各一个按钮,右边的添加按钮会根据主页面存储的cityArray进行判断,如果cityArray中已经存在“大理”,那么添加按钮按下后,并不能重复添加。
列表
右下方的添加按钮我是设置在最后一个cell,所以无论添加几个城市,按钮都在最下面,不会与已经有内容的cell重叠。
根据点击的cell的indexPath,传值相应的页数,进入主页面时也在对应的城市上。
主页面
主页面最下面是一个大的scrollView,宽度是(城市个数*屏幕宽度),高度是屏幕高度,每页都是一个小的scrollView,可上下翻动
仍然是由cityArray属性传值传进来,以便确认有几个城市要存几页,网络申请几个字典
下方是pageControl和一个主菜单按钮,可以返回列表页面。
对pageControl设置的方式:
_pageControl = [[UIPageControl alloc]init];
//_pageControl.center = CGPointMake(width/2-50, height-30);
_pageControl.frame = CGRectMake(100, height-30, 228, 30);
_pageControl.numberOfPages = _cityArray.count;
_pageControl.currentPage = _page;
//[_pageControl setBounds:CGRectMake(0, 0, 16*_cityArray.count, 16)];
[_pageControl.layer setCornerRadius:20];
[_pageControl setBackgroundColor: [UIColor clearColor]];
_pageControl.pageIndicatorTintColor = [UIColor grayColor];
_pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
[self.view addSubview:_pageControl];
显然还需要scrollView的协议函数,让pageControl随翻页自动变换。
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
[self.backScroll reloadInputViews];
}
- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
int page = scrollView.contentOffset.x/width;
_pageControl.currentPage = page;
}