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
同样用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"
}
}
}