天气预报仿写总结

news2024/9/19 21:13:37

目录

前言

首页

搜索页

详情页

浏览页


前言

这周学习了iOS中简单的网络请求,并完成了天气预报的仿写,这篇博客来做一下总结。天气预报主要要实现四个界面,接下来分四个界面分别讲解一下。

首页

首页的布局就是上方两个很简单的控件添加按钮和“天气”logo,下面一个动态变化的数据视图tableview。

这个数据视图的每一个单元格都需要一个城市实时的天气信息。

我的思路是数据视图的行数由一个数组的数量来确定,这个数组存放的是城市的名字,并且对于每一个城市的名字,都要申请网络请求来获得城市ID,进一步获得当前天气状态和七天的天气状态,从而获得数据视图的数据。

在进行更新数据源这一步时,我遇到的一个问题就是网络请求的异步,由于网络请求的异步机制,在有多个网络请求时,程序不是按顺序执行,申请完一个请求再进行下一个,而是多个网络请求同时在后台进行,因此在网络请求的回调里获取完某一项数据更新数据源时,就总会出现数据源为空或者数组越界的情况。

我的解决思路是:分为两种情况,第一种是需要网络请求有序完成,我采取网络请求嵌套的方法,例如获取城市天气需要先获得城市ID,那么我就在获取城市ID的回调中来获取所有与天气有关的数据;第二种是网络请求可以无序完成,那我就在每一个网络请求的回调里都做一次判断,当我所需要的数据都不为空并且数组元素数量达到要求时,进行数据视图的reloadData。

这里给出获取城市ID的API和获取实时天气的API以做示范

- (void)createURLForCityID {
    [self.cityIDMutableArray removeAllObjects];
    for (NSString* city in self.cityMutableArray) {
        //处理字符
        NSString* urlString = [NSString stringWithFormat:@"https://geoapi.qweather.com/v2/city/lookup?location=%@&key=34e1f7a3ef5544d393fcafaea08f0f1b&range=cn", city];
        NSLog(@"%@", urlString);
        urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        //创建URL
        NSURL* url = [NSURL URLWithString:urlString];
        //创建请求类
        NSURLRequest* request = [NSURLRequest requestWithURL:url];
        //创建会话
        NSURLSession* session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        //根据会话创建任务
        NSLog(@"12%@", urlString);
        NSURLSessionTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (error) {
                NSLog(@"无法获取城市ID");
            } else {
                NSDictionary* dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
                if (error) {
                    NSLog(@"无法获取城市ID");
                } else {
                    NSArray* array = dictionary[@"location"];
                    NSDictionary* nowcity = array[0];
                    NSLog(@"%@", nowcity[@"id"]);
                    [self.cityIDMutableArray addObject:nowcity[@"id"]];
                    NSLog(@"citycount:%d %d",self.cityMutableArray.count, self.cityIDMutableArray.count);
                    if (self.cityMutableArray.count == self.cityIDMutableArray.count) {
                        [self createURLForNow];
                        [self createURLForDay];
                    }
                }
            }
        }];
        [dataTask resume];
    }
}
- (void)createURLForNow {
    [self.tempMutableArray removeAllObjects];
    [self.stateMutableArray removeAllObjects];
    for (NSString* cityID in self.cityIDMutableArray) {
        //处理字符
        
        NSString* urlString = [NSString stringWithFormat:@"https://devapi.qweather.com/v7/weather/now?location=%@&key=34e1f7a3ef5544d393fcafaea08f0f1b", cityID];
        urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
        //创建URL
        NSLog(@"%@", urlString);
        NSURL* url = [NSURL URLWithString:urlString];
        //创建请求类
        NSURLRequest* request = [NSURLRequest requestWithURL:url];
        //创建会话
        NSURLSession* session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        //根据会话创建任务
        NSURLSessionTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (error) {
                NSLog(@"无法获取天气信息");
            } else {
                NSDictionary* dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
                if (error) {
                    NSLog(@"无法获取天气信息");
                } else {
                    NSDictionary* nowWeather = dictionary[@"now"];
                    [self.tempMutableArray addObject:[nowWeather[@"temp"] stringByAppendingString:@"°C"]];
                    if (self.lowAndHighMutableArray.count == self.cityMutableArray.count && self.stateMutableArray.count == self.cityMutableArray.count && self.tempMutableArray.count == self.cityMutableArray.count) {
                                [self.tableView reloadData];
                    }
                }
            }
        }];
        [dataTask resume];
    }
}

搜索页

搜索页面的布局其实也很简单,一个searchBar和一个同样动态变化的数据视图tableview。

这个界面要实现一个模糊搜索的功能,这里其实获取城市ID的API是有模糊搜索的功能的,所以只需要在调用API申请网络数据后,将得到的城市数据放入数组里,再重新加载数据视图就可以了

详情页

这个界面的布局相对比较复杂,但其实也还好,就是在数据视图上实现五个cell,关于布局的部分只是繁琐难度并不大就不多说了。这个界面需要接收上一个界面点击某个单元格时那个城市的ID(注意一定要是ID,笔者一开始传的是城市的名字,出现的问题就是当出现同名城市时,往往只能获取固定某一个城市的天气),在获取完ID后,再在详情页申请网络请求获取天气信息。笔者这里判定网络请求完成的条件非常复杂,这里给出我的判定条件

if (self.lowAndHigh != NULL && self.state != NULL && ![self.temp isEqualToString:@""] && !self.tableView && self.tempForHoursMutableArray.count == 24 && self.hoursMutableArray.count == 24 && self.daysMutableArray.count == 7 && self.tempForDaysMutableArray.count == 7 && self.sunrise != NULL && self.sunset != NULL && self.see != NULL && self.rain != NULL && self.iconForHoursMutableArray.count == 24 && self.iconForDaysMutableArray.count == 7) {
                        [self createBackgroundView:self.state];
                        [self createATableview];
                        //NSLog (@"tianshu:%ld",self.tempForDaysMutableArray.count);
                        //NSLog(@"tempOK");
                    }

 这个界面还要实现一个将城市添加到主页的功能,那么就获取当前城市ID,使用通知传值传到首页,遍历首页ID数组查重,如未重复,则在城市和城市ID数组中添加当前城市名和ID即可。(注意:查重时一定要使用城市ID,因为可以存在不同身份同名的城市,例如:黑龙江省的西安和陕西西安应该是可以同时出现在首页的)

浏览页

浏览页的本质就是一个滚动视图,只是这个滚动视图上的图片不是通过image类型获取的,而是直接拿的视图控制器的view属性,多次创建不同的详情页视图控制器,再将详情页的view放入滚动视图就可以实现。需要注意的是,这里需要将详情页视图控制器作为浏览页的子视图控制器,再将他的视图view放入滚动视图,否则就会出现一系列错位问题。

除此之外,添加子视图控制器和添加子视图控制器视图的顺序也会导致代码运行的差别,如果先添加视图,那么在添加视图时会调用一次子视图控制器的viewWillApear,当父视图控制器调用viewWillApear时,又会调用一次子视图控制器的viewWillApear。颠倒顺序的话,则子视图控制器只调用一次viewWillApear。

    self.scrollview = [[UIScrollView alloc] init];
    self.scrollview.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
    self.scrollview.contentSize = CGSizeMake([UIScreen mainScreen].bounds.size.width * self.cityMutableArray.count, 800);
    self.scrollview.delegate = self;
    self.scrollview.pagingEnabled = YES;
    NSLog(@"%ld", self.cityMutableArray.count);
    for (int i = 0; i < self.cityMutableArray.count; i++) {
        CGFloat xOffset = i * self.view.bounds.size.width;
        NSLog(@"%lf", xOffset);
        DetailViewController* detailViewController = [[DetailViewController alloc] init];
        //detailViewController.exitButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        detailViewController.cityName = self.cityMutableArray[i];
        detailViewController.cityID = self.cityIDMutableArray[i];
        detailViewController.view.frame = CGRectMake(xOffset, 0, self.view.bounds.size.width, self.view.bounds.size.height);
        [self addChildViewController:detailViewController];
        [self.scrollview addSubview:detailViewController.view];
    }
    self.scrollview.contentOffset = CGPointMake(_nowPage * [UIScreen mainScreen].bounds.size.width, 0);

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

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

相关文章

【人工智能基础三】卷积神经网络基础(CNN)

文章目录 1. 卷积神经网络结构2. 卷积神经网络计算2.1. 卷积层计算2.2. 池化层计算2.3. 全连接层计算 3. 典型卷积神经网络3.1. AlexNet3.2. VGGnet 卷积神经网络(Convolutional Neural Network&#xff0c;CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Ne…

1、 window平台opencv下载编译, 基于cmake和QT工具链

1. 环境准备&#xff0c;源码下载 1.1 前置环境 qt 下载安装cmake 安装&#xff0c;可参考&#xff1a; https://blog.csdn.net/qq_51355375/article/details/139186681 1.2 opencv 源码下载 官网地址&#xff1a; https://opencv.org/releases/ 下载源码&#xff1a; 2 …

(2024,∞-Brush,无限维扩散,希尔伯特空间,超分辨率,跨注意力神经算子,线性注意)具有无限维度扩散模型的可控大图像合成

∞-Brush: Controllable Large Image Synthesis with Diffusion Models in Infinite Dimensions 目录 0. 摘要 1. 简介 2. 相关工作 4. 提出的方法 4.1 函数空间中的条件扩散模型 4.2 带有跨注意力神经算子的条件去噪器 5. 实验 6. 限制 7. 结论 0. 摘要 将复杂、特定…

【C++】C++11(可变参数模板、lambda表达式、包装器)

文章目录 1. 可变参数模板1.1 介绍1.2 emplace系列接口实现 2. lambda表达式2.1 语法介绍2.2 原理 3. 包装器4. bind 1. 可变参数模板 1.1 介绍 可变参数我们在C语言阶段已经了解过了&#xff0c;C语言中叫做可变参数列表&#xff0c;其中使用 ... 代表可变参数。 C语言中的可…

百款精选的HTML5小游戏源码,你可以下载并直接运行在你的小程序或者自己的网站上

今天我带来了一份特别的礼物——百款精选的HTML5小游戏源码&#xff0c;你可以下载并直接运行在你的小程序或者自己的网站上&#xff0c;只需双击index.html即可开始。无论你是在寻找创意引流&#xff0c;还是想为你的网站增添互动性&#xff0c;这些小游戏都能帮你实现&#x…

Arch Linux - 2-安装中文输入法

文章目录 2 安装中文输入法2.0 准备2.0.1 前置条件2.0.2 建议 2.1 方案一&#xff1a;RimeIBus2.1.1 安装&配置2.1.2 添加输入法 2.2 方案二&#xff1a;IBusLibpinyin 2 安装中文输入法 2.0 准备 2.0.1 前置条件 预装gnome # 安装 pacman -S gnome# 设置开机自启动 sy…

开放式耳机有什么用?市面上热门的四款蓝牙耳机推荐

开放式耳机的用处相当广泛。 其一&#xff0c;它在耳朵健康方面表现出色。长期使用入耳式或者封闭式耳机&#xff0c;容易致使耳道处于潮湿状态、细菌大量滋生&#xff0c;甚至诱发耳部疾病。而开放式耳机不会阻塞耳道&#xff0c;能够使耳朵维持通风且干燥的状态&#xff0c;…

分享5款漂亮、简洁的登录页面模板分享,拿来即用(二)

文章目录 前言一、Bootstrap Material 风格的登录模板二、简洁清晰的jQuery登录模板三、防知乎的登录模板四、背景动态变化的登录模板五、背景动态变化的登录模板2六、深色背景登录模板 前言 在做管理系统的时候&#xff0c;有时为了做一个漂亮简洁的登录页面&#xff0c;对应…

【Log4j2】log4j-users-guide 官方文档阅读笔记

文章目录 前言1. Log4j2 架构直观了解2. Logger 的树状结构及 additivity3. Logger 的 Level 属性4. Filter 的结构5. Filter 作用的规则 前言 原文 Apache Log4j 官方文档 pdf需求 将指定包目录的日志打到指定文件中将 ERROR 日志单独打到指定文件中 目标 理解 log4j2 的架构…

java学习--集合

集合简介 关系示例图 Collection接口实现类的特点 Collection接口常用方法 Collection接口遍历元素方式&#xff1a; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator;/* author:我与java相爱相杀---c语言梦开始的地方 今天又是努力学习的…

【vulnhub】The Ether: Evil Science靶机

靶机安装 下载地址&#xff1a;https://www.vulnhub.com/entry/the-ether-evilscience-v101,212/ 运行环境&#xff1a;Vmware 信息收集 进行IP发现 nmap 192.168.93.0/24 进行端口扫描,开放了80和22端口 nmap -A 192.168.93.155 -p- 进行目录扫描 dirsearch -u http://…

MATLAB(15)分类模型

一、前言 在MATLAB中&#xff0c;实现不同类型的聚类&#xff08;如K-means聚类、层次聚类、模糊聚类&#xff09;和分类&#xff08;如神经网络分类&#xff09;需要用到不同的函数和工具箱。下面我将为每种方法提供一个基本的示例代码。 二、实现 1. K-means聚类 % 假设X是…

现代前端架构介绍(第一部分):App是如何由不同的构建块构成的

远离JavaScript疲劳和框架大战&#xff0c;了解真正重要的东西 几周前&#xff0c;我的同事们对我们的前端架构、代码结构和面临的挑战很感兴趣。在做了几次关于如何构建可扩展且健壮的前端的演讲后&#xff0c;我觉得把它们都总结一下并与社区分享我们的策略是一个不错的主意。…

主机安装要点

1.选择主板时&#xff0c;一定要先看能不能与 CPU 匹配得上。 2.后缀带 K 的 CPU&#xff0c;因为支持超频&#xff0c;也最好搭配 支持超频 系列主板。 3.主板尺寸大小E-ATX 加大板、ATX 大板、M-ATX 小板、ITX 迷你板&#xff0c;符合机箱大小。 4.部分主板不带A-RGB,有灯…

OpenHarmony应用开发和Android应用开发区别

OpenHarmony 和 Android 是两个不同的操作系统平台&#xff0c;各自有其独特的开发环境和架构。以下是 OpenHarmony 应用开发与 Android 应用开发之间的主要区别&#xff1a; 1. 架构设计 OpenHarmony 微内核架构&#xff1a;OpenHarmony 采用微内核设计&#xff0c;核心功…

中科院2区SCI,稳定检索39年!不收版面费,审稿友好,最快6周录用,速投!

关注GZH【欧亚科睿学术】&#xff0c;第一时间了解期刊最新动态&#xff01; 中科院2区SCI&#xff0c;最快6周录用&#xff01; MACHINE LEARNING 是一本国际性期刊&#xff0c;由知名出版社SPRINGER出版&#xff0c;创刊于1986年&#xff0c;一直致力于发布报道高质量的机器…

2、 qt平台opencv引入,和工程搭建

1. 准备工作 opencv 编译&#xff0c; 参考&#xff1a; https://blog.csdn.net/qq_51355375/article/details/140857966vscode qt cmake工程创建及环境搭建&#xff1a; https://blog.csdn.net/qq_51355375/article/details/140752130 2. 引入opencv 头文件和链接库 2.1 配…

大数据信用报告查询注意事项

在当今这个数据驱动的时代&#xff0c;大数据信用报告已成为评估个人信用状况的重要参考。无论是申请贷款、租房还是求职&#xff0c;一份良好的信用报告都能为您加分不少。然而&#xff0c;在查询大数据信用报告时&#xff0c;有几点注意事项不容忽视&#xff0c;以确保您的信…

CAN通信编程

ubuntu使用虚拟can 1. sudo modprobe vcan //加载虚拟can模块 2. sudo ip link add dev can0 type vcan //添加can0网卡 3. ifconfig -a //查看can0 4. sudo ip link set dev can0 up //开启can0 5. sudo ip link set dev can0 down //关闭can0 6. sudo ip link del dev can0 /…

图数据库 Nebula Graph下载安装

1. 安装包下载解压 进入官网https://www.nebula-graph.com.cn/download&#xff0c;下载对应版本 tar -zxvf nebula-graph-3.8.0.ubuntu2004.amd64.tar.gz cd nebula-graph-3.8.0.ubuntu2004.amd64/2. 启动 Nebula Graph 服务 2.1 修改配置文件名以应用配置 将子目录etc中的…