天气app的收获
无论如何,是基于MVC模式,但都是从UI页面开始设计,然后根据输入的城市名称,将其传入到model层,进行相对应的处理。
对于controler层,需要通过一些协议完成一些输入的反馈,例如输入完后按回车键,或者是点击屏幕上相对应的按键,应该需要结束输入,这里就涉及到了委托模式,我们作为委托者,在VC中完成协议中的内容。
对于model层,首先是网络这个模块,我们需要调用API,这是首次接触这个东西,他会返回给我们一个JSON格式的内容,所以我们需要对其进行解码,然后还了解到了使用quick type 可以根据JSON生成的内容,快速生成对应的结构体,最后为了提高代码的复用性,我们在model层同意设置了委托,即对于model层而言,我并没有把其和controller层写死,而是让controler层遵循其中的协议,这样在未来可能会有其他地方使用model层,同样也只需要遵循协议即可。
回到controller层,我们需要更新UI,但显然,它崩溃了,这时候需要使用DispatchQueue.main.async
使用场景
1. 更新 UI:
如果你在后台线程(例如网络请求、数据解析等)处理了某些任务,但需要更新 UI(如刷新标签、按钮或图像),你必须切换到主线程。
2. 避免崩溃:
在非主线程上操作 UI 会导致应用崩溃,因此 DispatchQueue.main.async 可以安全地切换到主线程。
最后添加一个根据自身所在位置获得当前位置的天气
在 Swift 中,获取用户当前位置的步骤如下:
1. 导入必要的框架
需要导入 CoreLocation 框架,这是 iOS 中用于处理位置相关功能的框架。
import CoreLocation
2. 创建 CLLocationManager 实例
创建一个 CLLocationManager 对象,用于管理和获取位置信息。
3. 配置权限
请求用户授权获取位置信息。
• 在 Info.plist 文件中添加以下键,提示用户为什么需要位置服务:
• NSLocationWhenInUseUsageDescription(仅在应用程序使用时获取位置)
• 或 NSLocationAlwaysUsageDescription(应用程序始终获取位置)
然后在代码中请求权限:
let locationManager = CLLocationManager()locationManager.requestWhenInUseAuthorization()// 或者 locationManager.requestAlwaysAuthorization()
4. 设置 CLLocationManager 代理
实现代理方法以处理位置更新。
class ViewController: UIViewController, CLLocationManagerDelegate {let locationManager = CLLocationManager()override func viewDidLoad() { super.viewDidLoad() // 设置代理 locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest // 设置精度 locationManager.requestWhenInUseAuthorization() // 请求权限 locationManager.startUpdatingLocation() // 开始更新位置}// 处理位置更新func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { if let location = locations.last { print("纬度: \(location.coordinate.latitude), 经度: \(location.coordinate.longitude)") }}// 处理错误func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { print("获取位置失败: \(error.localizedDescription)")}}
5. 处理隐私和错误
• 如果用户拒绝授予权限,应用需要友好地提示用户。
• 在 locationManager(_:didFailWithError:) 中处理错误。
总结
完整的步骤包括:
1. 导入 CoreLocation 框架。
2. 创建 CLLocationManager 实例。
3. 在 Info.plist 配置权限描述。
4. 在代码中请求位置权限。
5. 设置代理,监听位置更新。
6. 处理位置更新和错误。
需要注意的是,我们在获取了当前位置的信息后,需要手动停止相关的调用。
1. 持续触发 didUpdateLocations:
• 如果 stopUpdatingLocation() 不被调用,didUpdateLocations 会频繁调用,导致频繁地获取当前位置并调用 weathermanager.fetchWeather(latitude:longitutde:)。
• 这会覆盖用户输入的城市搜索结果,导致 UI 始终显示当前位置的天气信息,而不是用户想要查询的其他城市天气。
2. 竞争条件:
• resetPressed 和用户搜索功能共享同一个 weathermanager 实例。
• 如果 didUpdateLocations 继续触发,它可能在用户输入搜索城市后,立即再次覆盖 UI,造成用户感知上的问题。