集合视图不显示数据
Collection View Not Showing Data
我的目标是将来自名为 News API 的 Web 服务的数据显示到集合视图控制器中。下面是数据模型和网络管理器。
struct News: Codable {
var status: String?
var totalResults: Int?
var articles: [Article]?
var article: Article?
enum CodingKeys: String, CodingKey {
case status = "status"
case totalResults = "totalResults"
case articles = "articles"
}
}
// MARK: - Article
struct Article: Codable {
var source: Source?
var author: String?
var title: String?
var articleDescription: String?
var url: String?
var urlToImage: String?
var publishedAt: String?
var content: String?
enum CodingKeys: String, CodingKey {
case source = "source"
case author = "author"
case title = "title"
case articleDescription = "description"
case url = "url"
case urlToImage = "urlToImage"
case publishedAt = "publishedAt"
case content = "content"
}
}
// MARK: - Source
struct Source: Codable {
var id: ID?
var name: Name?
enum CodingKeys: String, CodingKey {
case id = "id"
case name = "name"
}
}
enum ID: String, Codable {
case engadget = "engadget"
case techcrunch = "techcrunch"
case theVerge = "the-verge"
}
enum Name: String, Codable {
case engadget = "Engadget"
case lifehackerCOM = "Lifehacker.com"
case techCrunch = "TechCrunch"
case theVerge = "The Verge"
}
class NetworkManger{
static let shared = NetworkManger()
private let baseURL: String
private var apiKeyPathCompononent :String
private init(){
self.baseURL = "https://newsapi.org/v2/everything?q=NFT&sortBy=popularity&"
self.apiKeyPathCompononent = "apiKey=d32071cd286c4f6b9c689527fc195b03"
}
private var jsonDecoder:JSONDecoder = {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return decoder
}()
func getArticles() {
AF.request(self.baseURL + self.apiKeyPathCompononent, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil, interceptor: nil).response { (responseData) in
guard let data = responseData.data else {return}
do {
let news = try self.jsonDecoder.decode(News.self, from: data)
let nc = NotificationCenter.default
nc.post(name: Notification.Name("didFinishParsing"), object: nil)
} catch {
print(error)
}
}
}
}
它可以将来自网络服务的数据显示到控制台。问题是它无法向 NewsVC 中的集合视图显示数据。我已经完成了所有必要的步骤,例如实现集合视图数据源、使用观察者提醒 NewsVC JSON 已解析、设置集合视图布局和注册单元格,但似乎没有任何效果。下面的代码是 NewVc 和 News 网格;新闻Vc是为了展示内容。
class NewsVC: UIViewController {
var news = [Article]()
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
configureCollection()
NetworkManger.shared.getArticles()
}
func configureCollection(){
collectionView.delegate = self
collectionView.dataSource = self
let collectionviewFlowLayout = UICollectionViewFlowLayout()
collectionviewFlowLayout.scrollDirection = .vertical
collectionviewFlowLayout.itemSize = CGSize(width: 188.0, height: 264.0)
collectionviewFlowLayout.minimumInteritemSpacing = 10.0
collectionView.collectionViewLayout = collectionviewFlowLayout
NotificationCenter.default.addObserver(self, selector: #selector(refreshcollectionView), name: Notification.Name("didFinishParsing"), object: nil)
}
@objc func refreshcollectionView(_ notification:Notification) {
guard let news = notification.object as? Article else { return}
print("News == \(news)")
self.news = [news]
print("Coount == \(self.news.count)")
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
extension NewsVC:UICollectionViewDataSource , UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
news.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! NewsGridCell
let stories = news[indexPath.item]
cell.setCells(stories)
cell.backgroundColor = UIColor.red
return cell
}
class NewsGridCell: UICollectionViewCell {
@IBOutlet weak var newsImage: UIImageView!
@IBOutlet weak var newsDescription: UILabel!
@IBOutlet weak var author: UILabel!
func setCells(_ news:Article){
upDateUI(newDescription:news.articleDescription, author: news.author)
}
private func upDateUI(newDescription:String? , author:String?){
self.newsDescription.text = newDescription
self.author.text = author
}
}
阅读代码片段后,代码看起来应该可以工作,但实际上没有。在那种情况下,我会添加 debugPrint(#function)
来检查是否执行了以下方法:
NewsVC -> collectionView(_:numberOfItemsInSection:)
NewsVC -> collectionView(_:cellForItemAt:)
NewsGridCell -> setCells(_:)
如果那些 debugPrints 打印到控制台,那么我会去“View Hierarchy inspector”检查存在和视图的大小。
尝试代替
nc.post(name: Notification.Name("didFinishParsing"), object: nil)
发送
nc.post(name: Notification.Name("didFinishParsing"), object: news)
然后代替
guard let news = notification.object as? Article else { return}
写
guard let news = notification.object as? News else { return}
print("News == \(news)")
self.news = news.articles
我的目标是将来自名为 News API 的 Web 服务的数据显示到集合视图控制器中。下面是数据模型和网络管理器。
struct News: Codable {
var status: String?
var totalResults: Int?
var articles: [Article]?
var article: Article?
enum CodingKeys: String, CodingKey {
case status = "status"
case totalResults = "totalResults"
case articles = "articles"
}
}
// MARK: - Article
struct Article: Codable {
var source: Source?
var author: String?
var title: String?
var articleDescription: String?
var url: String?
var urlToImage: String?
var publishedAt: String?
var content: String?
enum CodingKeys: String, CodingKey {
case source = "source"
case author = "author"
case title = "title"
case articleDescription = "description"
case url = "url"
case urlToImage = "urlToImage"
case publishedAt = "publishedAt"
case content = "content"
}
}
// MARK: - Source
struct Source: Codable {
var id: ID?
var name: Name?
enum CodingKeys: String, CodingKey {
case id = "id"
case name = "name"
}
}
enum ID: String, Codable {
case engadget = "engadget"
case techcrunch = "techcrunch"
case theVerge = "the-verge"
}
enum Name: String, Codable {
case engadget = "Engadget"
case lifehackerCOM = "Lifehacker.com"
case techCrunch = "TechCrunch"
case theVerge = "The Verge"
}
class NetworkManger{
static let shared = NetworkManger()
private let baseURL: String
private var apiKeyPathCompononent :String
private init(){
self.baseURL = "https://newsapi.org/v2/everything?q=NFT&sortBy=popularity&"
self.apiKeyPathCompononent = "apiKey=d32071cd286c4f6b9c689527fc195b03"
}
private var jsonDecoder:JSONDecoder = {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return decoder
}()
func getArticles() {
AF.request(self.baseURL + self.apiKeyPathCompononent, method: .get, parameters: nil, encoding: URLEncoding.default, headers: nil, interceptor: nil).response { (responseData) in
guard let data = responseData.data else {return}
do {
let news = try self.jsonDecoder.decode(News.self, from: data)
let nc = NotificationCenter.default
nc.post(name: Notification.Name("didFinishParsing"), object: nil)
} catch {
print(error)
}
}
}
}
它可以将来自网络服务的数据显示到控制台。问题是它无法向 NewsVC 中的集合视图显示数据。我已经完成了所有必要的步骤,例如实现集合视图数据源、使用观察者提醒 NewsVC JSON 已解析、设置集合视图布局和注册单元格,但似乎没有任何效果。下面的代码是 NewVc 和 News 网格;新闻Vc是为了展示内容。
class NewsVC: UIViewController {
var news = [Article]()
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
configureCollection()
NetworkManger.shared.getArticles()
}
func configureCollection(){
collectionView.delegate = self
collectionView.dataSource = self
let collectionviewFlowLayout = UICollectionViewFlowLayout()
collectionviewFlowLayout.scrollDirection = .vertical
collectionviewFlowLayout.itemSize = CGSize(width: 188.0, height: 264.0)
collectionviewFlowLayout.minimumInteritemSpacing = 10.0
collectionView.collectionViewLayout = collectionviewFlowLayout
NotificationCenter.default.addObserver(self, selector: #selector(refreshcollectionView), name: Notification.Name("didFinishParsing"), object: nil)
}
@objc func refreshcollectionView(_ notification:Notification) {
guard let news = notification.object as? Article else { return}
print("News == \(news)")
self.news = [news]
print("Coount == \(self.news.count)")
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
extension NewsVC:UICollectionViewDataSource , UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
news.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! NewsGridCell
let stories = news[indexPath.item]
cell.setCells(stories)
cell.backgroundColor = UIColor.red
return cell
}
class NewsGridCell: UICollectionViewCell {
@IBOutlet weak var newsImage: UIImageView!
@IBOutlet weak var newsDescription: UILabel!
@IBOutlet weak var author: UILabel!
func setCells(_ news:Article){
upDateUI(newDescription:news.articleDescription, author: news.author)
}
private func upDateUI(newDescription:String? , author:String?){
self.newsDescription.text = newDescription
self.author.text = author
}
}
阅读代码片段后,代码看起来应该可以工作,但实际上没有。在那种情况下,我会添加 debugPrint(#function)
来检查是否执行了以下方法:
NewsVC -> collectionView(_:numberOfItemsInSection:)
NewsVC -> collectionView(_:cellForItemAt:)
NewsGridCell -> setCells(_:)
如果那些 debugPrints 打印到控制台,那么我会去“View Hierarchy inspector”检查存在和视图的大小。
尝试代替
nc.post(name: Notification.Name("didFinishParsing"), object: nil)
发送
nc.post(name: Notification.Name("didFinishParsing"), object: news)
然后代替
guard let news = notification.object as? Article else { return}
写
guard let news = notification.object as? News else { return}
print("News == \(news)")
self.news = news.articles