我是初學者。我通過api提取單元格中的圖片。一切都是建立的,但不是圖片 - 它是空的。回傳零。我在這里坐了一整天,想不通!
API 鏈接 - https://swiftbook.ru//wp-content/uploads/api/api_courses
如果這個答案在某個地方,我很抱歉,如果提供鏈接不難,請發送,謝謝。
非常感謝您的幫助和澄清!
在此處輸入影像描述
import UIKit
class CourseCell: UITableViewCell {
@IBOutlet var courseImage: UIImageView!
@IBOutlet var courseNameLabel: UILabel!
@IBOutlet var numberOfLessons: UILabel!
@IBOutlet var numberOfTests: UILabel!
func configure(with course: Course) {
courseNameLabel.text = course.name
numberOfLessons.text = "Number of lessons \(course.number_of_lessons ?? 0)"
numberOfTests.text = "Number of tests \(course.number_of_tests ?? 0)"
DispatchQueue.global().async {
guard let stringUrl = course.imageUrl,
let imageURL = URL(string: stringUrl),
let imageData = try? Data(contentsOf: imageURL)
else {
return
}
DispatchQueue.main.async {
self.courseImage.image = UIImage(data: imageData)
}
}
}
}
JSON解碼模型
Course.swift
struct Course: Decodable {
let name: String?
let imageUrl: String?
let number_of_lessons: Int?
let number_of_tests: Int?
}
struct WebsiteDescription: Decodable {
let courses: [Course]?
let websiteDescription: String?
let websiteName: String?
}
以及來自 CoursesViewController.swift 的一段帶有 JSON 的代碼
extension CoursesViewController {
func fetchCourses() {
guard let url = URL(string: URLExamples.exampleTwo.rawValue) else { return }
URLSession.shared.dataTask(with: url) { (data, _, _) in
guard let data = data else {
return
}
do {
// получаем курсы в переменную
self.courses = try JSONDecoder().decode([Course].self, from: data)
// и мы должны перезагрузить таблицу
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch let error {
print(error)
}
}.resume()
}
}
這是我可能得到的零(請看下面的截圖)
在此處輸入影像描述
uj5u.com熱心網友回復:
我試圖制作另一個版本的代碼并且它能夠運行。您可以檢查我的代碼并與您自己的代碼進行比較。
CoursesViewController
class CoursesViewController: UIViewController {
private lazy var tableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .plain)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.register(CourseCell.self, forCellReuseIdentifier: "CourseCell")
tableView.delegate = self
tableView.dataSource = self
return tableView
}()
private var courses: [Course] = []
override func viewDidLoad() {
super.viewDidLoad()
setupViews()
setupLayout()
fetchCourses()
}
private func setupViews() {
view.addSubview(tableView)
}
private func setupLayout() {
tableView.snp.makeConstraints { make in
make.edges.equalToSuperview()
}
}
private func fetchCourses() {
guard let url = URL(string: "https://swiftbook.ru//wp-content/uploads/api/api_courses") else {
return
}
URLSession.shared.dataTask(with: url) { (data, _, _) in
guard let data = data else {
return
}
do {
// получаем курсы в переменную
self.courses = try JSONDecoder().decode([Course].self, from: data)
// и мы должны перезагрузить таблицу
DispatchQueue.main.async {
self.tableView.reloadData()
}
} catch let error {
print(error)
}
}.resume()
}
}
extension CoursesViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
courses.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "CourseCell", for: indexPath) as? CourseCell else {
return UITableViewCell()
}
cell.configure(with: courses[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
120
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
120
}
}
細胞
class CourseCell: UITableViewCell {
private lazy var nameLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.textColor = .black
label.font = .systemFont(ofSize: 14, weight: .bold)
return label
}()
private lazy var courseImage = UIImageView(frame: .zero)
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupViews()
setupLayout()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func configure(with course: Course) {
nameLabel.text = course.name
DispatchQueue.global().async {
guard let stringUrl = course.imageUrl,
let imageURL = URL(string: stringUrl),
let imageData = try? Data(contentsOf: imageURL)
else {
return
}
DispatchQueue.main.async {
// Make sure it's the same course
self.courseImage.image = UIImage(data: imageData)
}
}
}
private func setupViews() {
courseImage.contentMode = .scaleAspectFill
contentView.addSubview(nameLabel)
contentView.addSubview(courseImage)
}
private func setupLayout() {
nameLabel.snp.makeConstraints { make in
make.top.leading.trailing.equalToSuperview().inset(8)
}
courseImage.snp.makeConstraints { make in
make.centerX.equalToSuperview().inset(8)
make.top.equalTo(nameLabel.snp.bottom).offset(12)
make.height.width.equalTo(80)
}
}
}
- 在我看來,您應該檢查您的 UI 布局,以確保可以正確加載和顯示影像視圖。
一些改進建議
Course.swift: 請為變數名使用小寫駝峰式約定,因為它是常見的 Swift 約定CourseCell.swift:由于課程沒有 ID,因此在您從背景加載影像一段時間后,由于重用單元機制,該單元可能被另一個單元使用。
DispatchQueue.main.async {
// Make sure it's the same course
if course.id == self.course.id {
self.courseImage.image = UIImage(data: imageData)
}
}
- 每次從服務器加載影像時使用快取機制,以便下次不需要再次從服務器獲取(您可以設定快取超時)
- 您可以使用著名的 3rd 方庫(例如
SDWebImage或KingFisher.
uj5u.com熱心網友回復:
樓上的答案太好了!!!這對我來說是一個額外的寶貴經驗!
但主要原因是在我國被封鎖的 .ru 域。當我不小心打開 MAC 上的 VPN 并構建應用程式時,一切都加載了!!!因為我現在在烏克蘭,我們封鎖了所有 .ru 域,API URL 就在 .ru 上
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/495106.html
