问题描述
只是想问问我是否正确调用了 API,因为我的 TableView 中没有显示数据(我是 UIKit 的新手)。我关注了 this tutorial,将其调整为我需要的网址。
我认为问题在于我如何进行 API 调用,因为我的数组仍然为空?我相信这是一个 REST API,所以这可能是问题吗?
我也在以编程方式执行此操作,因此主故事板是空白的。
模型数据:
import Foundation
class ArtistSearchModelData{
// var artists = [Artists]()
public func loadArtists(searchTerm: String,completionHandler: @escaping([Artists]) -> Void){
guard let url = URL(string: "https://musicbrainz.org/ws/2/artist/?query=artist:\(searchTerm)") else {
print("URL is invalid")
return
}
let dataTask = URLSession.shared.dataTask(with: url){ data,response,error in
if let data = data {
if let artistResponse = try? JSONDecoder().decode(ArtistResponse.self,from: data){
completionHandler(artistResponse.artists ?? [])
}
return
}
guard let httpResponse = response as? HTTPURLResponse,(200...299).contains(httpResponse.statusCode) else{
print("Error with response: \(response)")
return
}
if let error = error {
print("Error Thrown : \(error)")
return
}
}
dataTask.resume()
}
}
视图控制器:
import UIKit
class ViewController: UIViewController {
let tableView = UITableView()
var safeArea: UILayoutGuide!
var artists: [Artists]?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
safeArea = view.layoutMarginsGuide
setUpTable()
setUpNavigation()
}
func setUpTable(){
ArtistSearchModelData().loadArtists (searchTerm: "Fred"){ [weak self] (artists) in
self?.artists = artists
dispatchQueue.main.async{
self?.tableView.reloadData()
}
}
view.addSubview(tableView)
//populate with data
tableView.delegate = self
tableView.dataSource = self
tableView.register(UITableViewCell.self,forCellReuseIdentifier: "cell")
//turn off autoresizing
tableView.translatesAutoresizingMaskIntoConstraints = false
//Layout Configs
tableView.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
func setUpNavigation(){
navigationItem.title = "Artists"
self.navigationController?.navigationBar.barTintColor = .gray
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
}
}
extension ViewController: UITableViewDataSource,UITableViewDelegate{
func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
if let artistsCount = artists {
return artistsCount.count
}else{
return 0
}
}
func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell",for: indexPath)
cell.textLabel?.text = artists![indexPath.row].id
return cell
}
func tableView(_ tableView: UITableView,heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100.0
}
}
型号:
import Foundation
//http://musicbrainz.org/ws/2/artist/?query=artist:SEARCHTERM
struct ArtistResponse: Codable{
let artists : [Artists]
}
struct Artists: Codable{
let id: String
let type: String
let name: String
let country: String
let disambiguation: String
}
应用委托:
import UIKit
@main
class AppDelegate: UIResponder,UIApplicationDelegate {
func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// MARK: UIScenesession Lifecycle
func application(_ application: UIApplication,configurationForConnecting connectingScenesession: UIScenesession,options: UIScene.Connectionoptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration",sessionRole: connectingScenesession.role)
}
func application(_ application: UIApplication,diddiscardScenesessions scenesessions: Set<UIScenesession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running,this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes,as they will not return.
}
}
场景代理:
import UIKit
class SceneDelegate: UIResponder,UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene,willConnectTo session: UIScenesession,options connectionoptions: UIScene.Connectionoptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard,the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingScenesession` instead).
guard let _ = (scene as? UIWindowScene) else { return }
}
func sceneDiddisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background,or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later,as its session was not necessarily discarded (see `application:diddiscardScenesessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data,release shared resources,and store enough scene-specific state information
// to restore the scene back to its current state.
}
}
解决方法
由于某些值变为空且未处理,请更新可编码模型并检查其是否有效:
struct ArtistResponse: Codable{
let artists : [Artist]
}
struct Artist: Codable{
let id: String?
let type: String?
let name: String?
let country: String?
let disambiguation: String?
}