【iOS】App仿写--天气预报

文章目录

  • 前言
  • 一、首页
  • 二、搜索界面
  • 三、添加界面
  • 四、浏览界面
  • 总结


前言

最近完成了暑假的最后一个任务——天气预报,特此记录博客总结。根据iPhone中天气App的功能大致可以将仿写的App分为四个界面——首页,搜索界面,添加界面,浏览界面,同时在天气预报中调用了较多的API,具体使用方法可以看这篇博客——【iOS】json数据解析以及简单的网络数据请求,这里不再说明

一、首页

对于首页,笔者将北京作为城市数组的第一个元素,后续可以通过搜索界面与添加界面对首页的城市进行添加
在这里插入图片描述
这里需要注意的是,因为我们的天气是实时变化的,所以我们只需要得到添加的城市名,然后通过城市名来得到实时的天气

另外需要注意的是因为我们的每个城市的天气的背景图片是不同的,然而我们自定义cell的在其出列时就已经被设置好,后面再去在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;方法中设置背景图片就会将自定义cell中原本自定义的控件覆盖掉

所以需要如下代码设置我们的背景图片:

    NSString *imageName = [NSString stringWithFormat:@"%ld.jpg", (indexPath.section + 1)];UIImage *image = [UIImage imageNamed:imageName];// 创建一个 UIImageView,并设置其内容为图片UIImageView *imageView = [[UIImageView alloc] initWithImage:image];imageView.frame = cell.contentView.bounds;imageView.contentMode = UIViewContentModeScaleAspectFill;imageView.clipsToBounds = YES;// 将 UIImageView 添加到 cell.contentView 的底部[cell.contentView insertSubview:imageView atIndex:0];

这样就做到了我们的背景图片不会覆盖我们cell中的控件,当然我们也可以在我们的对应的TableViewCell函数中设置我们的背景图片,只不过这样设置的背景图片比较单一,所以这里在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;方法中进行设置。


二、搜索界面

首先我们来看一下我们搜索界面的效果
在这里插入图片描述
可以看到我们的搜索结果会根据输入的文字进行实时变化

笔者这里使用的搜索栏是UISearchBar,我们在h文件中添加对应协议使用监听,即可实现我们的搜索的实时变化

- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText;   // called when text changes (including clear)

三、添加界面

我们先来看一下效果
在这里插入图片描述
可以看到我们这里利用搜索界面打开对应城市区县的天气之后点击添加按钮,相应的城市或区县就会被添加到首页,这里实际上使用了我们的通知传值,同样的,如果存在相同城市,那么就添加失败。具体有关通知传值的方法可以看这篇博客——【iOS】多界面传值
在这里插入图片描述

//添加界面
- (void)addCity {int boo = 0;for (id object in _hasCityArray) {//判断是否存在相同城市if ([object isEqualToString:_cityID]) {boo = 1;break;}}if (boo == 0) {//不存在[_dictionary setValue:_cityID forKey:@"key"];[[NSNotificationCenter defaultCenter] postNotificationName:@"notice" object:nil userInfo:_dictionary];NSLog(@"%@", _cityID);[self dismissViewControllerAnimated:YES completion:nil];} else {//存在self.alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"该城市已存在" preferredStyle:UIAlertControllerStyleAlert];UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {}];[self.alert addAction:confirmAction];[self presentViewController:self.alert animated:YES completion:nil];}
}//首页界面
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotice:)
name:@"notice" object:nil];- (void)receiveNotice:(NSNotification *)send {[_cityIDArray addObject:send.userInfo[@"key"]];[self createData];
}

另外在这里笔者使用了SVGKit第三方库,因为在笔者调用的API中图标是以SVG的格式给出的,但是原生的Xcode并不支持SVG格式的图片,因此需要用到第三方库SVGKit,具体怎么使用第三方库在这篇博客【iOS】Cocoapods的安装以及使用中已经讲解过如何使用。

但是需要注意的一点是我们导入的SVGKit无法直接使用,会出现如下的问题 "Module 'CocoaLumberjack' not found" using CocoaPods,这是CocoaPods本身的问题,如何解决这个问题,笔者在这篇回答中找到了答案——Build problem “Module ‘CocoaLumberjack’ not found” using CocoaPods #543
在这里插入图片描述


笔者在这里给出部分API的调用代码供大家参考

- (void)creatUrl_Days {
//    //1.创建请求地址NSString *urlString = [NSString stringWithFormat:@"https://devapi.qweather.com/v7/weather/7d?location=%@&key=4c75fbc6961d404289bf6b44d9009576", _cityID];//处理字符urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];//创建URLNSURL *url = [NSURL URLWithString:urlString];NSLog(@"%@", urlString);//2.创建请求类NSURLRequest *request = [NSURLRequest requestWithURL:url];//3.创建会话//delegateQueue 表示协议方法在哪个线程中执行//    NSURLSession *session = [NSURLSession sharedSession];用于简单的网络请求NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self  delegateQueue:[NSOperationQueue mainQueue]];//4.根据会话创建任务NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {if (error) {// 请求出错处理} else {NSDictionary *weatherData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];int count = 0;if (error) {// 解析数据出错处理} else {// 解析数据成功NSArray *dailyArray = weatherData[@"daily"];if (dailyArray.count > 0) {for (NSDictionary *currentDayData in dailyArray) {NSString *temperature_Low = currentDayData[@"tempMin"]; // 低NSString *temperature_High = currentDayData[@"tempMax"]; // 低NSString *temperature = [NSString stringWithFormat:@"%@°~%@°", temperature_Low, temperature_High];NSString *timeString = currentDayData[@"fxDate"]; // 时间NSLog(@"%@", timeString);NSString *time = [timeString substringWithRange:NSMakeRange(5, 5)];NSString *icon = currentDayData[@"iconDay"];// 将时间和温度分别添加到数组中[self.dayArray_Days addObject:time];[self.iconArray_Days addObject:icon];[self.temperatureArray_Days addObject:temperature];//                          NSLog(@"%@的温度为:%@, 图标代码为%@", time, temperature, icon);
//                          break;if (count == 0) {self->_highestT.text = [NSString stringWithFormat:@"最高%@°", temperature_High];self->_lowestT.text = [NSString stringWithFormat:@"最低%@°", temperature_Low];count++;self->_sunRise = currentDayData[@"sunrise"];self->_sunSet = currentDayData[@"sunset"];self->_precip = currentDayData[@"precip"];self->_uvIndex = currentDayData[@"uvIndex"];NSLog(@"%@, %@", self->_sunRise, currentDayData[@"sunrise"]);}}[[NSOperationQueue mainQueue] addOperationWithBlock:^{[self->_tableView2 reloadData];[self->_tableView3 reloadData];[self->_tableView4 reloadData];[self->_tableView5 reloadData];[self->_tableView6 reloadData];}];} else {NSLog(@"无法获取当前时间的天气数据。");}}}}];// 启动数据任务[dataTask resume];}

这里需要注意的是笔者这里将从API得到的数据存到对应的数组中, 然后在将数组中的元素呈现到我们的自定义cell上。

同时这里给出笔者调用的对应的API
每日天气预报

四、浏览界面

在这里插入图片描述
笔者这里将首页中的城市都传入了浏览界面,核心思路就是利用我们的UIScrollView,我们先前实现轮播图的思路是在UIScrollView中添加图片实现滚动,我们这里就将图片换成对应城市的视图控制器即可

//首页
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {ScrollViewController *t = [[ScrollViewController alloc] init];t.cityIDArray = _cityIDArray;t.nowPage = indexPath.section;t.modalPresentationStyle = 0;[self presentViewController:t animated:YES completion:nil];
}//ScrollViewController添加对应城市视图
for (int i = 0; i < _cityIDArray.count; i++) {CGFloat xOffset = i * self.view.bounds.size.width;MenuShowViewController *t = [[MenuShowViewController alloc] init];t.cityID = _cityIDArray[i];NSString *t1 = [NSString stringWithFormat:@"%d.jpg", (i + 1)];t.view.layer.contents = (__bridge id _Nullable)([UIImage imageNamed:t1].CGImage);t.view.frame = CGRectMake(xOffset, 0, self.view.bounds.size.width, self.view.bounds.size.height);[self addChildViewController:t];[self.scrollView addSubview:t.view];[t didMoveToParentViewController:self];
}

同时笔者这里给出实现pageControl固定在视图底部的实现代码

self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height -
50, self.view.bounds.size.width, 50)];
self.pageControl.numberOfPages = _cityIDArray.count;
self.pageControl.currentPage = self.nowPage;
self.pageControl.pageIndicatorTintColor = [UIColor grayColor]; // 未选中页码的颜色
self.pageControl.currentPageIndicatorTintColor = [UIColor blackColor]; // 当前选中页码的颜色
[self.view addSubview:self.pageControl];

其实核心就是[self.view addSubview:self.pageControl];无论我们的ScrollView如何滚动,我们的view是不变的,因此将pageControl添加到view中即可实现分页控件的固定


总结

暑假的App仿写已经全部写完,后面回去学习一些第三方库例如Masonry与AFNetworking

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/19970.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PostgreSQL-数据库命令

PostgreSQL-数据库命令 介绍 一个数据库是一个或多个模式的集合,而模式包含表、函数等。因此,完整的逻辑组织结构层次是服务器实例(PostgreSQL Server)、数据库(Database)、模式(Schema)、表(Table),以及某些其他对象(如函数)。一个PostgreSQL服务器实例可以管理…

【NLP概念源和流】 04-过度到RNN(第 4/20 部分)

接上文 【NLP概念源和流】 03-基于计数的嵌入,GloVe(第 3/20 部分) 一、说明 词嵌入使许多NLP任务有了显著的改进。它对单词原理图的理解以及将不同长度的文本表示为固定向量的能力使其在许多复杂的NLP任务中非常受欢迎。大多数机器学习算法可以直接应用于分类和回归任务的…

【vue】 vue2 监听滚动条滚动事件

代码 直接上代码&#xff0c;vue单文件 index.vue <template><div class"content" scroll"onScroll"><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容</p><p>内容…

PyTorch - GPU入门教程1

1. 安装GPU版本的PyTorch 登录PyTorch官网https://pytorch.org/&#xff0c;下载对应CUDA版本的PyTorch【不能直接pip install&#xff0c;否则安装上的是CPU版本的】 2. 查看GPU信息 &#xff08;1&#xff09;重要信息 !nvidia-smi我的GPU版本很垃圾&#xff0c;本blog仅…

COMSOL三维多孔介质3D多相材料颗粒夹杂复合材料达西渗流模拟

在实际工程中渗流路径往往不是单一材料&#xff0c;如渗流发生在夹杂碎石的土体中&#xff0c;这就造成渗流的复杂性。这里采用两项材料通过COMSOL达西定律模块对渗流进行模拟。 模型采用CAD随机球体颗粒&过渡区插件建立后导入到COMSOL软件内。 模型包括渗流发生的外侧基…

SOP/详解*和**/python数据结构(iter,list,tuple,dict)/ 解包

一、错误解决合集 1. > combined_seq.named_children() 2. isinstance 2th parameter : must be a type or tuple of types > 改为tuple&#xff0c;不要用列表。改为 LLLayer (nn.Conv2d,nn.Linear) 3. File “test.py”, line 90, in calculate_fin_fout print(“hi”…

实战-单例模式和创建生产者相结合

实际中遇到了这样一个问题&#xff1a; The producer group[xxxx] has been created before, specify another instanceName (like producer.setInstanceName) please. 发生的原因是&#xff1a;一个进程内&#xff0c;创建了多个相同topic的producer。 所以问题就转换成了如何…

非线性弹簧摆的仿真(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

<van-empty description=““ /> 滚动条bug

使用 <van-empty description"" /> 时&#xff0c;图片出现了个滚动条&#xff0c;图片可以上下滑动。 代码如下&#xff1a; <block wx:if"{{courseList.length < 0}}"><van-empty description"" /> </block> <…

教你使用Pyinstaller将Python源码打包成可执行程序exe的方法

pyinstaller是一个常用的Python打包工具&#xff0c;可以将Python程序打包成独立的可执行文件&#xff0c;支持Windows、Linux和macOS等平台。 ★★★Pyinstaller有许多参数&#xff0c;以下是其中一些主要参数的含义&#xff1a; -F, --onefile&#xff1a;打包一个单个文件…

项目管理困扰?这里有个6W3H解决方案

引言 在项目管理的过程中&#xff0c;我们经常面临各种各样的挑战和问题。例如&#xff0c;如何确定项目的目标&#xff1f;如何分配资源&#xff1f;何时开始执行项目&#xff1f;在哪里进行项目&#xff1f;这些问题如果没有得到正确的解答&#xff0c;将会严重影响项目的进…

【C++】初阶 --- 引用(超级详细版!!!)

文章目录 &#x1f36a;一、引用的概念&#x1f36a;二、引用的特性&#x1f37f;1、引用在定义时必须初始化&#x1f37f;2、一个变量可以有多个引用&#x1f37f;3、引用一旦引用一个实体&#xff0c;再不能引用其他实体 &#x1f36a;三、常引用(被const 修饰的引用)&#x…

Flink读取mysql数据库(java)

代码如下: package com.weilanaoli.ruge.vlink.flink;import com.ververica.cdc.connectors.mysql.source.MySqlSource; import com.ververica.cdc.connectors.mysql.table.StartupOptions; import com.ververica.cdc.debezium.JsonDebeziumDeserializationSchema; import org…

Excel修改日期格式,改变日期的筛选方式

我们有两列日期数据&#xff1a; 左边这一列筛选会显示&#xff1a; 右边这一列筛选会显示&#xff1a; 修改格式&#xff0c;将【日期1】改为【日期2】 将【日期1】的格式修改为文本格式即可 修改格式&#xff0c;将【日期2】改为【日期1】 选中日期2&#xff0c;点击【数据…

JDK各版本重要变革

各版本更新详情 JDK8(LTS)--2014/3 语法层面 lambda表达式(重要特色之一) 一种特殊的匿名内部类,语法更加简洁允许把函数作为一个方法的参数,将代码象数据一样传递&#xff0c;即将函数作为方法参数传递基本语法: <函数式接口> <变量名> (参数...) -> { 方法…

什么是Java中的JVMTI(JVM Tool Interface)?

Java中的JNI&#xff08;Java Native Interface&#xff09;和JVMTI&#xff08;JVM Tool Interface&#xff09;都是与Java运行时环境&#xff08;JVM&#xff09;交互的工具&#xff0c;但它们有不同的目的和使用场景。下面我从新手的角度来幽默地解释一下它们的区别和用途。…

LeetCode 热题 100 JavaScript --226. 翻转二叉树

给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 3&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 提示&#xff1a; 树中节点数目范围在 [0, 100] 内 -100 < Node.val < 100 var invertTree function(root…

哈工大计算机网络课程网络安全基本原理详解之:消息完整性与数字签名

哈工大计算机网络课程网络安全基本原理详解之&#xff1a;消息完整性与数字签名 这一小节&#xff0c;我们继续介绍网络完全中的另一个重要内容&#xff0c;就是消息完整性&#xff0c;也为后面的数字签名打下基础。 报文完整性 首先来看一下什么是报文完整性。 报文完整性…

基于springboot+jpa+mysql+html网上中药商城系统

基于springbootjpamysqlhtml网上中药商城系统 一、系统介绍二、功能展示1.主页(客户)2.登陆&#xff08;客户&#xff09;3.注册&#xff08;客户&#xff09;4.购物车(客户)5.我的订单&#xff08;客户&#xff09;6.用户管理&#xff08;管理员&#xff09;7.分类管理&#x…

代理模式是什么

目录 代理模式 代理模式的组成 代理模式的作用 静态代理 静态代理实现步骤: 静态代理的缺点 动态代理 动态代理的实现 JDK 动态代理&#xff08;接口代理&#xff09; jdk动态代理核心 JDK 动态代理类实现步骤: CGLIB动态代理 CGLIB动态代理的核心 CGLIB 动态代理…