【发布时间】:2021-09-26 08:56:36
【问题描述】:
目前我正在尝试从 News API 加载数据,在此之前我曾尝试使用 UITableView 实现它并且它可以工作,但它在 UICollectionView 中不起作用。我正在使用 URLSession 进行网络操作。
PS; 我使用 Storyborad 中对象库中的预制 collectionView 完成此操作
我期望发生的事情
- JSON 数据加载到 CollectionView 中
实际发生的情况
- CollectionView 中未加载 JSON,屏幕为空
我尝试解决的问题
- 在附加 JSON 后重新加载 collectionView
NewsCollectionVC.swift
class NewsCollectionVC: UIViewController {
var newsResult = [NewsModel]()
var newsManager = NewsManager()
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
newsManager.fetchNews()
newsManager.delegate = self
collectionView.reloadData()
}
}
extension NewsCollectionVC : NewsManagerDelegate {
func didSendNewsData(_ newsManager: NewsManager, with news: [NewsModel]) {
self.newsResult.append(contentsOf: news)
DispatchQueue.main.async{
self.collectionView.reloadData()
print(self.newsResult.count)
}
}
}
extension NewsCollectionVC : UICollectionViewDataSource{
// Tell delegate how many cv need to show
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return newsResult.count
}
// Tell delegate content of cv
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let listOfNews = newsResult[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CViewCell
cell.author.text = listOfNews.author
//cell.author.text = "listOfNews.author"
return cell
}
}
NewsManager.swift
protocol NewsManagerDelegate {
func didSendNewsData (_ newsManager: NewsManager, with news : [NewsModel])
}
struct NewsManager{
var delegate : NewsManagerDelegate?
let newsUrl = "https://newsapi.org/v2/everything?q=apple"
let key = "MY_API_KEY"
func fetchNews(){
let urlString = "\(newsUrl)&apiKey=\(key)"
performRequest(with : urlString)
}
func fetchNews(page : Int){
let urlString = "\(newsUrl)&page=\(page)&apiKey=\(key)"
performRequest(with: urlString)
}
func performRequest(with urlString : String){
// 1. create URL object
guard let url = URL(string: urlString) else {fatalError("There's problem to fetch data from this url")}
// 2. create session, object to do networking
let session = URLSession(configuration: .default)
//3. give session a task
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil{
print("Error in giving session a task \(String(describing: error?.localizedDescription))")
} else{
// determine if data is exist
if let safeData = data {
//convert data to string
//let dataString = String(data: safeData, encoding: .utf8)
//print(dataString)
// Parse the data here
guard let news = parseJSON(safeData) else{ fatalError("Error parsing data from JSON")}
DispatchQueue.main.async {
delegate?.didSendNewsData(self, with: news)
}
}
}
}
//start the task
task.resume()
}
func parseJSON(_ newsData : Data) -> [NewsModel]?{
let decoder = JSONDecoder()
var newsModel = [NewsModel]()
do{
let decodeData = try decoder.decode(NewsData.self, from: newsData)
print(decodeData.articles[0].title)
print(decodeData.articles[0].source.name)
print(decodeData.articles[0].urlToImage)
for article in decodeData.articles {
let author = article.author
let title = article.title
let decription = article.description
let url = article.url
let urlToImage = article.urlToImage
let publishedAt = article.publishedAt
let sourcesName = article.source.name
guard let imageData = try? Data(contentsOf: urlToImage) else{fatalError("Error to get image data from URL")}
guard let imageContent = UIImage(data: imageData) else {fatalError("Error load image from image data")}
let data = NewsModel(author: author, title: title, decription: decription, url: url, image: imageContent, publishedAt: publishedAt, sourcesName: sourcesName)
newsModel.append(data)
}
return newsModel
} catch{
print("Error decode the data : \(error.localizedDescription)")
}
return newsModel
}
}
NewsModel.swift
struct NewsModel {
let author : String
let title : String
let decription : String
let url : String
let image : UIImage
let publishedAt : String
let sourcesName : String
}
【问题讨论】:
-
你有没有试过在添加断点后运行你的代码,看看它的哪一部分失败了?
-
@Abizern ya 我已经在断点处,似乎 numberOfItemsInSection 为 0,我不知道为什么,当我在 tableview 尝试它时它返回 20
-
@EricAya 如您所见,我解码 JSON 并将其解析回数据模型,单个类中可能有多个 URLSession ????,我打算使用它您建议的一种方法,但我找不到如何做到这一点。
-
您是否在您的委托方法中放置了一个断点以查看 何时 它正在运行?
-
@Abizern 我只是尝试在 newsManagerDelegate 和采用它的类中添加断点,它都返回成功而不是 nil
标签: ios swift uicollectionview