【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]];
    //创建URL
    NSURL *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.mfbz.cn/a/59567.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

dflow工作流使用1——架构和基本概念

对于容器技术、工作流等概念完全不懂的情况下理解dflow的工作方式会很吃力&#xff0c;这里记录一下个人理解。 dflow涉及的基本概念 工作流的概念很好理解&#xff0c;即某个项目可以分为多个步骤&#xff0c;每个步骤可以实现独立运行&#xff0c;只保留输入输出接口&#x…

WebGL Shader着色器GLSL语言

在2D绘图中的坐标系统&#xff0c;默认情况下是与窗口坐标系统相同&#xff0c;它以canvas的左上角为坐标原点&#xff0c;沿X轴向右为正值&#xff0c;沿Y轴向下为正值。其中canvas坐标的单位都是’px’。 WebGL使用的是正交右手坐标系&#xff0c;且每个方向都有可使用的值的…

c语言野指针int*p、空指针int*p = NULL、万能指针void* p

1、野指针&#xff0c;既没有初始化的指针&#xff0c;//如果没有给指针初始化&#xff0c;则指针p的内容为随机地址&#xff0c;会随机指向&#xff0c;故成为野指针&#xff0c;不可以操作野指针 #include "stdio.h" #include <stdlib.h>int main() {//1、野…

ORACLE常用基础

. 1.oracle开机启动流程 su - oracle lsnrctl start lsnrctl status sqlplus / as sysdba startup 2、如何查看数据库版本 select * from v$version; 3.如何查看用户从那个设备连接的数据库 SELECT DISTINCT machine , terminal FROM V$SESSION; 4.如何查看表结构 selec…

FANUC机器人SRVO-300机械手断裂故障报警原因分析及处理办法

FANUC机器人SRVO-300机械手断裂故障报警原因分析及处理办法 首先,我们查看报警说明书上的介绍: 总结:即在机械手断裂设置为无效时,机器人检测出了机械手断裂信号(不该有的信号,现在检测到了,所以报警) 使机械手断裂设定为无效/有效的具体方法:  按下示教器的MENU菜单…

Vue前端框架入门

文章目录 Vue快速入门Vue指令生命周期 Vue 经过一小段时间学习 我认为vue就是在原js上进行的一个加强 简化JS中的DOM操作 vue是分两个层的 一个叫做视图层(View)&#xff0c;你可以理解为展现出来的前端页面 一个叫数据模型层(Model),包含数据和一些数据的处理方法 MVVM就是实…

数据结构10 -查找_树表查找

创建二叉搜索树 二叉搜索树 二叉搜索树是有数值的了&#xff0c;二叉搜索树是一个有序树。 若它的左子树不空&#xff0c;则左子树上所有结点的值均小于它的根结点的值&#xff1b; 若它的右子树不空&#xff0c;则右子树上所有结点的值均大于它的根结点的值&#xff1b; 它…

从0到1开发go-tcp框架【2-实现Message模块、解决TCP粘包问题、实现多路由机制】

从0到1开发go-tcp框架【2-实现Message模块、解决TCP粘包问题、实现多路由机制】 1 实现\封装Message模块 zinx/ziface/imessage.go package zifacetype IMessage interface {GetMsdId() uint32GetMsgLen() uint32GetMsgData() []byteSetMsgId(uint32)SetData([]byte)SetData…

组合总和——力扣39

文章目录 题目描述回溯 题目描述 回溯 class Solution { public:vector<vector<int>> res;vector<int> seq; void dfs(vector<int>& nums, int pos, int target){if(target0){res.emplace_back(seq);return;}if(posnums.size()){return;}//直接跳过…

2023上半年手机及数码行业分析报告(京东销售数据分析)

2023年上半年&#xff0c;手机市场迎来复苏&#xff0c;同环比来看&#xff0c;销量销额纷纷上涨。 而数码市场中&#xff0c;各个热门品类表现不一。微单相机及智能手表同比去年呈现增长态势&#xff0c;而笔记本电脑市场则出现下滑。 基于此现状&#xff0c;鲸参谋发布了20…

Ubuntu 虚拟机和主机无法互相复制文字和文件

1.在虚拟机列表中&#xff0c;右键查看是否有安装VMware Tools&#xff0c;如果没有安装点击安装&#xff0c;如果已经安装了&#xff0c;上面显示重现安装VMware Tools&#xff0c;并且为灰色&#xff0c;如图&#xff1a; 2.如果没有安装点击安装&#xff0c;如果已经安装&am…

【知识产权】专利的弊端

接上篇【知识产权】著作权的作用_qilei2010的博客-CSDN博客。 ​ 1 专利的分类 首先,专利分为:发明专利、实用新型专利、外观设计专利。这里要说明的是专利的不同种类在不同的国家都是有不同规定的,并不是所有国家和地区都是分成这三类。 >国家法律法规数据库 >中华…

untiy代码打压缩包,可设置密码

1、简单介绍&#xff1a; 用的是一个插件SharpZipLib&#xff0c;在vs的Nuget下载&#xff0c;也可以去github下载https://github.com/icsharpcode/SharpZipLib 用这个最主要的是因为&#xff0c;这个不用请求windows的文件读写权限&#xff0c;关于这个权限我搞了好久&#…

51单片机(普中HC6800-EM3 V3.0)实验例程软件分析 实验四 蜂鸣器

目录 前言 一、原理图及知识点介绍 1.1、蜂鸣器原理图&#xff1a; 二、代码分析 前言 第一个实验:51单片机&#xff08;普中HC6800-EM3 V3.0&#xff09;实验例程软件分析 实验一 点亮第一个LED_ManGo CHEN的博客-CSDN博客 第二个实验:51单片机&#xff08;普中HC6800-EM…

快速文件传输常见问题

我们所处的世界充斥着各种信息&#xff0c;能够迅速获得正确的数据往往是企业成功的关键因素。将文件从A点移动到B点需要考虑很多问题&#xff0c;但是当涉及需要在最短时间内送达全球各地收件人的大型关键任务文件时&#xff0c;就不能再使用Dropbox和 Google Drive 等方案了。…

安全学习DAY13_WEB应用源码获取

信息打点-WEB应用-源码获取 文章目录 信息打点-WEB应用-源码获取小节概述-思维导图资产架构-源码获取&#xff08;后端&#xff09;后端-开源后端-闭源-源码泄露源码泄露原因源码泄露方式集合网站备份压缩包git&#xff0c;svn源码泄露DS_Store文件泄露composer.json 泄露资源搜…

C语言预备知识

安装Visual studio 官方网址 https://visualstudio.microsoft.com/zh-hans/ 选择第一个社区版本&#xff08;免费&#xff09; 下载完成后打开安装包 安装完成后会自动打开程序选择c项目然后安装即可&#xff08;c兼容c&#xff09; 安装完成后启动程序注意这里需要注册也可…

设备管理系统与物联网的融合:实现智能化设备监控和维护

在数字化时代&#xff0c;设备管理系统和物联网技术的融合为工业企业带来了巨大的变革和创新。本文将探讨设备管理系统与物联网的融合&#xff0c;重点介绍设备健康管理平台在实现智能化设备监控和维护方面的关键作用和优势。 一、设备管理系统与物联网的融合 随着物联网技术的…

OJ:C++ | [vector] — 力扣

文章目录 118. 杨辉三角 - 力扣思路解&#xff1a; 17. 电话号码的字母组合 - 力扣思路&#xff1a;递归解&#xff1a; 137. 只出现一次的数字 II- 力扣思路&#xff1a;解&#xff1a; 118. 杨辉三角 - 力扣 题目链接&#xff1a;118. 杨辉三角 - 力扣&#xff08;LeetCode&…

算法与数据结构(二十一)二叉树(纲领篇)

备注&#xff1a;本文旨在通过 labuladong 的二叉树&#xff08;纲领篇&#xff09;理解框架思维&#xff0c;用于个人笔记及交流学习&#xff0c;版权归原作者 labuladong 所有&#xff1b; 我刷了这么多年题&#xff0c;浓缩出二叉树算法的一个总纲放在这里&#xff0c;也许…