import UIKit
import GooglePlaces
import Alamofire
import CoreData
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return listData?.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CityCollectionViewCell
let city = listData![indexPath.row] as? NSDictionary
let name = city?.object(forKey: "name") as? String
let main = city?.object(forKey: "main") as! NSDictionary
let temp = main.object(forKey: "temp") as? Double
let date1 = city?.object(forKey: "dt")
let date = Date(timeIntervalSince1970: date1 as! TimeInterval)
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: "GMT") //Set timezone that you want
dateFormatter.locale = NSLocale.current
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm" //Specify your format that you want
let strDate = dateFormatter.string(from: date)
cell.cityLabel.text = name!
cell.lastUpdatedLabel.text = strDate
cell.tempLabel.text = "\(temp!)"
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
cv.deselectItem(at: indexPath, animated: true)
let row = indexPath.row;
let selectedCity = list![row];
userDefaults?.set(selectedCity, forKey: "citySelection");
self.performSegue(withIdentifier: "selectCity", sender: self);
}
@IBOutlet weak var cv: UICollectionView!
var userDefaults:UserDefaults?;
var list:NSMutableArray?
var listData:NSMutableArray?
let group = DispatchGroup()
override func viewDidLoad() {
super.viewDidLoad()
userDefaults = UserDefaults.standard;
}
@IBAction func addCity(_ sender: Any) {
let autocompleteController = GMSAutocompleteViewController()
autocompleteController.delegate = self
let addressFilter = GMSAutocompleteFilter()
addressFilter.type = .city
autocompleteController.autocompleteFilter = addressFilter
present(autocompleteController, animated: true, completion: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
updateValues()
}
func updateValues() {
let list = getSearchHistory()
print(list)
let count = list.count
if count > 0
{
for item in list {
group.enter()
getData(name: item as! String)
}
group.notify(queue: .main, execute: {
self.cv.reloadData()
})
}
}
func getData(name: String) {
let modified = name.replacingOccurrences(of: " ", with: "+")
let url = "http://api.openweathermap.org/data/2.5/weather?q=\(modified)&APPID=-------"
Alamofire.request(url, method: HTTPMethod.get).responseJSON(completionHandler: {
(response) -> Void in
let city = response.result.value as! NSDictionary;
self.listData?.add(city)
print(self.listData)
self.group.leave()
})
}
func addToSearchHistory(locationName:String) {
let delegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = delegate.persistentContainer.viewContext;
let entity = NSEntityDescription.insertNewObject(forEntityName: "SavedPlaces", into: managedContext)
entity.setValue(locationName, forKey: "name")
do {
try managedContext.save();
}
catch {
print("Core data error");
}
}
func getSearchHistory() -> NSMutableArray {
let returnData = NSMutableArray()
let delegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = delegate.persistentContainer.viewContext;
do {
let req = NSFetchRequest<NSFetchRequestResult>(entityName: "SavedPlaces");
let data = try managedContext.fetch(req) as! [NSManagedObject];
for item in data {
let name = item.value(forKey: "name") as? String;
returnData.add(name!);
}
}
catch {
print("Core data error");
}
return returnData;
}
}
extension ViewController: GMSAutocompleteViewControllerDelegate {
// Handle the user's selection.
func viewController(_ viewController: GMSAutocompleteViewController, didAutocompleteWith place: GMSPlace) {
self.addToSearchHistory(locationName: place.name)
dismiss(animated: true, completion: nil)
}
func viewController(_ viewController: GMSAutocompleteViewController, didFailAutocompleteWithError error: Error) {
// TODO: handle the error.
print("Error: ", error.localizedDescription)
}
// User canceled the operation.
func wasCancelled(_ viewController: GMSAutocompleteViewController) {
dismiss(animated: true, completion: nil)
}
// Turn the network activity indicator on and off again.
func didRequestAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
func didUpdateAutocompletePredictions(_ viewController: GMSAutocompleteViewController) {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
我尝试使用 core Data 从存储的数据中加载值,然后循环遍历字符串并调用 api,然后将其添加到一个新数组中,从中填充 Collection View 。
问题:我已正确填充所有值(城市名称)列表,但在调用 api 并调用“UpdateUI”函数后,我只得到一个单元格。 gif file
最佳答案
请求尚未完成,这是一个异步任务,等待我将为您处理代码,这样每当有新响应时,tableView 就会重新加载以反射(reflect)该情况
func updateValues() {
let list = getSearchHistory()
if !list.isEmpty
{
for item in list {
getData(name: item as! String)
}
}
}
func getData(name: String) {
let modified = name.replacingOccurrences(of: " ", with: "+")
let rr = NSMutableArray()
let url = "http://api.openweathermap.org/data/2.5/weather?q=\(modified)&APPID=------------------"
Alamofire.request(url, method: HTTPMethod.get).responseJSON(completionHandler: {
(response) -> Void in
let city = response.result.value as! NSDictionary;
rr.add(city)
self.listData.append(rr)
DispatchQueue.main.async
{
self.cv.reloadData()
}
})
}
另请注意一个非常重要的步骤,以响应您覆盖当前数组而不是附加到它
self.listData = rr
应该是
self.listData.append(rr)
无论是否发生加载,这都会导致永久显示一项
另外不要忘记在 viewDidLoad 中初始化 listData
listData = NSMutableArray()
尝试像这样解析 api
-(void)getDataforCity:(NSString*)cityName
{
NSURL*url = [NSURL URLWithString:[NSString stringWithFormat:@"%@?APPID=%@&q=%@",openWeatherMapBaseURL,openWeatherMapAPIKey,cityName]];
[NSURLSession.sharedSession dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if(error == nil)
{
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary*main = json[@"main"];
NSString*humidity = main[@"humidity"];
NSString*pressure = main[@"pressure"];
NSString*temp = main[@"temp"];
NSString*tempMax = main[@"temp_max"];
NSString*tempMin = main[@"temp_min"];
NSArray*weatherArr = json[@"weather"];
NSDictionary*weather = weatherArr[0];
NSString*description = weather[@"description"];
NSDictionary*wind = json[@"wind"];
NSString*deg = wind[@"deg"];
NSString*speed = wind[@"speed"];
NSLog(@"humidity %@ : ",humidity);
NSLog(@"pressure %@ : ",pressure);
NSLog(@"temp %@ : ",temp);
NSLog(@"tempMax %@ : ",tempMax);
NSLog(@"tempMin %@ : ",tempMin);
NSLog(@"description %@ : ",description);
NSLog(@"deg %@ : ",deg);
NSLog(@"speed %@ : ",speed);
NSLog(@"dasdasddasdataioioio : %@",json);
}
else
{
NSLog(@"dasdasddasdata : %@",error);
}
}].resume;
}
关于ios - 我正在尝试循环遍历字符串数组并触发 api 调用以重新加载 Collection View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48174549/