查询天气app

Main.storyboard 样式:
在这里插入图片描述
其中另外一个界面在控件中搜索ViewController即可
第一个页面左上角按钮的功能即跳转页面
按住control左键拖拽至下一页面选择Present Modally即可
在这里插入图片描述
在左边栏内按MVC模式整理好并且创建Weather.swift和SelectCityController.swift
在这里插入图片描述
选中新增的页面 将Class设置为SelectCityController
在这里插入图片描述

将新增的页面的控件拖到SelectCityController内

import UIKit

class SelectCityController: UIViewController {

    @IBOutlet weak var currentCityLabel: UILabel!
    @IBOutlet weak var cityInput: UITextField!
    
    @IBAction func changeCity(_ sender: Any) {
    }
    @IBAction func dismiss(_ sender: Any) {
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    

获取地址

系统自带的CoreLocation可以用来获取地址

import CoreLocation

在View Controller旁边遵循CLLocationManagerDelegate协议

class ViewController: UIViewController,CLLocationManagerDelegate {

创建变量实例化CLLocationManager

    let locationManager = CLLocationManager()

当程序运行时申请地址

override func viewDidLoad() {
        super.viewDidLoad()
        
        locationManager.delegate = self//CLLocationManager的代理人是self(viewcontroller)
        
        locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters//设置位置精度,精度越高,耗电越大
        locationManager.requestLocation()//请求用户位置--只请求一次
    }

当页面出现就执行

//每当页面出现就会执行
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        locationManager.requestWhenInUseAuthorization()//请求授权获取当前位置
    }

当请求用户位置的时候系统会立刻调用这个方法–系统调用,不需要我们自己调用

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let lat = locations[0].coordinate.latitude
        let lon = locations[0].coordinate.longitude
        print(lat,lon) //输出经纬度
    }

当获取位置失败时

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error)
        cityLabel.text = "获取位置失败"
    }

在左栏Info里添加Privacy
在这里插入图片描述
在这里插入图片描述
运行程序后在Debug里面选择Custom Location输入虚拟机的位置
在这里插入图片描述
运行后 结果
在这里插入图片描述
在这里插入图片描述

运用Alamofire来获取开源API
Alamofire文档
开源API网址
用Cocoapods来安装Alamofire
在这里插入图片描述
输入第11行代码,点击右上角install即可

复制文档里面usage里的方法
在这里插入图片描述
在这里插入图片描述
运用经纬度的方法获取当地的信息
在这里插入图片描述
在开源API的网址注册一个账号获得appid
写上刚刚载入的Alamofire

import Alamofire

存储自己的appid

let appid = "e72ca729af228beabd5d20e3b7749713"

写一个函数来得到当地天气的信息,输出获取到的JSON格式的信息

func getWeather(paras:[String:String]){
        Alamofire.request("https://api.openweathermap.org/data/2.5/weather",parameters: paras).responseJSON { response in
            //iflet针对可选类型数据进行判断
            if let json = response.result.value {
                print(json)
            }
        }

变量存储参数

let paras = ["lat":"\(lat)","lon":"\(lon)","appid":appid]

在申请地址后立刻调用函数获取

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let lat = locations[0].coordinate.latitude
        let lon = locations[0].coordinate.longitude
        print(lat,lon)
        let paras = ["lat":"\(lat)","lon":"\(lon)","appid":appid]
        getWeather(paras: paras)

    }

运行程序结果
在这里插入图片描述
运用SwiftyJSON来解析JSON

SwiftyJSON文档

同样用Cocoapods下载
在这里插入图片描述

在Weather.swift里面创建swift类

根据Weather condition codes写weather类里面的计算属性icon

import Foundation

class Weather{
    var temp = 0
    var city = ""
    var condition = 0
    
    //计算属性
    var icon:String{
        
        switch (condition) {
            
        case 0...300 :
            return "tstorm1"
            
        case 301...500 :
            return "light_rain"
            
        case 501...600 :
            return "shower3"
            
        case 601...700 :
            return "snow4"
            
        case 701...771 :
            return "fog"
            
        case 772...799 :
            return "tstorm3"
            
        case 800 :
            return "sunny"
            
        case 801...804 :
            return "cloudy2"
            
        case 900...903, 905...1000  :
            return "tstorm3"
            
        case 903 :
            return "snow5"
            
        case 904 :
            return "sunny"
            
        default :
            return "dunno"
        }
    }
}

添加swiftyJSON

import SwiftyJSON

实例化Weather

let weather = Weather()

函数获取JSON内城市名,温度,conditon的信息

func createWeather(weatherJSON:JSON){
        weather.city = weatherJSON["name"].stringValue
        weather.temp = Int(round(weatherJSON["main","temp"].doubleValue-273.15))
        weather.condition = weatherJSON["weather",0,"id"].intValue
    }

函数更新UI

func updateUI(){
        cityLabel.text = weather.city
        tempLabel.text = "\(weather.temp)˚"
        imageView.image = UIImage(named: weather.icon)
    }

getWeather函数调用上述两个函数

func getWeather(paras:[String:String]){
        Alamofire.request("https://api.openweathermap.org/data/2.5/weather",parameters: paras).responseJSON { response in
            //iflet针对可选类型数据进行判断
            if let json = response.result.value {
                let weather = JSON(json)
                
                self.createWeather(weatherJSON: weather)
                
                self.updateUI()
            }
        }
    }

运行app成功获得信息并且更新了UI
在这里插入图片描述

用extension ViewController整理代码

import UIKit
import CoreLocation
import Alamofire
import SwiftyJSON

class ViewController: UIViewController {
    
    let weather = Weather()
    let locationManager = CLLocationManager()
    let appid = "e72ca729af228beabd5d20e3b7749713"
    
    @IBOutlet weak var cityLabel: UILabel!
    @IBOutlet weak var tempLabel: UILabel!
    @IBOutlet weak var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        locationManager.delegate = self//CLLocationManager的代理人是self(viewcontroller)
        
        locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters//设置位置精度,精度越高,耗电越大
        locationManager.requestLocation()//请求用户位置--只请求一次
    }
    
    //每当页面出现就会执行
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        locationManager.requestWhenInUseAuthorization()//请求授权获取当前位置
    }
    
    //当请求用户位置的时候立刻调用这个方法--系统调用,不需要我们自己调用
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let lat = locations[0].coordinate.latitude
        let lon = locations[0].coordinate.longitude
        print(lat,lon)
        let paras = ["lat":"\(lat)","lon":"\(lon)","appid":appid]
        getWeather(paras: paras)

    }
   
}

extension ViewController: CLLocationManagerDelegate{
    func getWeather(paras:[String:String]){
        Alamofire.request("https://api.openweathermap.org/data/2.5/weather",parameters: paras).responseJSON { response in
            //iflet针对可选类型数据进行判断
            if let json = response.result.value {
                let weather = JSON(json)
                
                self.createWeather(weatherJSON: weather)
                
                self.updateUI()
            }
        }
    }
    func createWeather(weatherJSON:JSON){
        weather.city = weatherJSON["name"].stringValue
        weather.temp = Int(round(weatherJSON["main","temp"].doubleValue-273.15))
        weather.condition = weatherJSON["weather",0,"id"].intValue
    }
    
    //更新界面
    func updateUI(){
        cityLabel.text = weather.city
        tempLabel.text = "\(weather.temp)˚"
        imageView.image = UIImage(named: weather.icon)
    }
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error)
        cityLabel.text = "获取位置失败"
    }
}

实现输入城市查询信息的功能

复制新页面最下面的代码到ViewController里面,进行传值

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "selectCity"{
            //找到目的地页面的控制器,以便进行传值
            let vc = segue.destination as! SelectCityController
            vc.currentCity = weather.city
            vc.delegate = self
        }
    }

在新的controller里面创建变量进行接收值

var currentCity = ""

每次加载页面都接收传来的值,并更新UI

override func viewDidLoad() {
        super.viewDidLoad()
        currentCityLabel.text = currentCity
        // Do any additional setup after loading the view.
    }

写向第一个页面传值的protocl,定义函数

protocol selectCityDelegate {
    func selectCity(city:String)
}
var delegate:selectCityDelegate?

点击查询天气时调用selectCity函数,查询后把当前页面删除运用dismiss函数

@IBAction func selectCityButton(_ sender: UIButton) {
        delegate?.selectCity(city: cityInput.text!)
        dismiss(animated: true, completion: nil)
    }

在ViewController内写入SelectCityDelegate

extension ViewController: CLLocationManagerDelegate,SelectCityDelegate{

实现selectCity函数

func selectCity(city: String) {
   let paras = ["q":city,"appid":appid]
   getWeather(paras: paras)
}

最后实现效果:
在这里插入图片描述
在这里插入图片描述

最后实现的代码:
ViewController:

import UIKit
import CoreLocation
import Alamofire
import SwiftyJSON

class ViewController: UIViewController {
    
    let weather = Weather()
    let locationManager = CLLocationManager()
    let appid = "e72ca729af228beabd5d20e3b7749713"
    
    @IBOutlet weak var cityLabel: UILabel!
    @IBOutlet weak var tempLabel: UILabel!
    @IBOutlet weak var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        locationManager.delegate = self//CLLocationManager的代理人是self(viewcontroller)
        
        locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters//设置位置精度,精度越高,耗电越大
        locationManager.requestLocation()//请求用户位置--只请求一次
    }
    
    //每当页面出现就会执行
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        locationManager.requestWhenInUseAuthorization()//请求授权获取当前位置
    }
    
    //当请求用户位置的时候立刻调用这个方法--系统调用,不需要我们自己调用
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let lat = locations[0].coordinate.latitude
        let lon = locations[0].coordinate.longitude
        print(lat,lon)
        let paras = ["lat":"\(lat)","lon":"\(lon)","appid":appid]
        getWeather(paras: paras)

    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "selectCity"{
            //找到目的地页面的控制器,以便进行传值
            let vc = segue.destination as! SelectCityController
            vc.currentCity = weather.city
            
            vc.delegate = self
        }
    }
   
}

extension ViewController: CLLocationManagerDelegate,SelectCityDelegate{
    func selectCity(city: String) {
        let paras = ["q":city,"appid":appid]
        getWeather(paras: paras)
    }
    
    
    func getWeather(paras:[String:String]){
        Alamofire.request("https://api.openweathermap.org/data/2.5/weather",parameters: paras).responseJSON { response in
            //iflet针对可选类型数据进行判断
            if let json = response.result.value {
                let weather = JSON(json)
                
                self.createWeather(weatherJSON: weather)
                
                self.updateUI()
            }
        }
    }
    func createWeather(weatherJSON:JSON){
        weather.city = weatherJSON["name"].stringValue
        weather.temp = Int(round(weatherJSON["main","temp"].doubleValue-273.15))
        weather.condition = weatherJSON["weather",0,"id"].intValue
    }
    
    //更新界面
    func updateUI(){
        cityLabel.text = weather.city
        tempLabel.text = "\(weather.temp)˚"
        imageView.image = UIImage(named: weather.icon)
    }
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print(error)
        cityLabel.text = "获取位置失败"
    }
}

SelectCityController:

import UIKit
protocol SelectCityDelegate {
    func selectCity(city:String)
}

class SelectCityController: UIViewController {
    var currentCity = ""
    var delegate:SelectCityDelegate?
    @IBAction func disMiss(_ sender: UIButton) {
        dismiss(animated: true, completion: nil)
    }
    @IBOutlet weak var currentCityLabel: UILabel!
    @IBOutlet weak var cityInput: UITextField!
    
    @IBAction func selectCityButton(_ sender: UIButton) {
        delegate?.selectCity(city: cityInput.text!)
        dismiss(animated: true, completion: nil)
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        currentCityLabel.text = currentCity
        // Do any additional setup after loading the view.
    }
}

Weather:

import Foundation

class Weather {
    var city = ""
    var temp = 0
    var condition = 0
    
    var icon:String{
        switch condition {
            case 1...300:
                return "tstorm1"
            case 301...500:
                return "light_rain"
            case 501...600:
                return "shower3"
            case 601...700:
                return "snow4"
            case 701...771:
                return "fog"
            case 772...799:
                return "tstorm3"
            case 800:
                return "sunny"
            case 801...804:
                return "cloudy2"
            case 900...903, 905...1000:
                return "tstorm3"
            case 903:
                return "snow5"
            case 904:
                return "sunny"
            default:
                return "dunno"
        }
    }
}

发布了6 篇原创文章 · 获赞 8 · 访问量 352

猜你喜欢

转载自blog.csdn.net/qq_44864362/article/details/100174123
今日推荐