I'm trying to make a search application using MusicBrainz API, where the API will return JSON data that matches the search term typed in by the user.
This is what I have so far of my UI:
import UIKit
import WebKit
class ArtistListViewController: UIViewController{
let tableView = UITableView()
var safeArea: UILayoutGuide!
var artists: [Artists]?
let textField = UITextField()
var searchTerm = "Search"
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
safeArea = view.layoutMarginsGuide
searchBar()
setUpTable()
setUpNavigation()
}
func searchBar(){
view.addSubview(textField)
textField.placeholder = "Search"
textField.frame = CGRect(x: 10,y: 200,width: 300.0,height: 30.0)
textField.borderStyle = UITextField.BorderStyle.line
textField.translatesAutoresizingMaskIntoConstraints = false
//Layout Configs
textField.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
textField.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
textField.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
textField.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
func setUpTable(){
view.addSubview(tableView)
ArtistSearchModelData().loadArtists(searchTerm: "Adele"){ [weak self] (artists) in
self?.artists = artists
DispatchQueue.main.async{
self?.tableView.reloadData()
}
}
//populate with data
tableView.delegate = self
tableView.dataSource = self
tableView.register(TableViewCell.self, forCellReuseIdentifier: "cell")
//turn off autoresizing
tableView.translatesAutoresizingMaskIntoConstraints = false
//Layout Configs
tableView.topAnchor.constraint(equalTo: view.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(){
self.navigationItem.title = "Artists"
self.navigationController?.navigationBar.barTintColor = .white
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.titleTextAttributes = [
NSAttributedString.Key.foregroundColor: UIColor.orange,
NSAttributedString.Key.font: UIFont(name: "Arial-BoldMT", size: 30)
]
}
}
This is what my UI looks like:
As you can see my search bar is completely missing and I have no idea how to render it.
I tried using a UIStackView but got the same results.
I've tried searching the internet and found similar solutions but couldn't get any of them to work.
Adding both textField and tableView to a custom subview renders nothing too, maybe because they're functions? Am I just going about this the wrong way?
Any help is appreciated!
You constrain your text field to the top of the view:
textField.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
then, you constrain your table view to the top of the view:
tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
So your table view is covering your text field.
You could do this:
tableView.topAnchor.constraint(equalTo: textField.bottomAnchor).isActive = true
To constrain the Top of the table view to the Bottom of the text field.
As a side note, you should constrain to the view's Safe Area ... not to the view itself:
textField.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
Edit
Here is your class with the above modifications (note that I commented-out the stuff I don't have access to, such as your Artist
specific code):
class ArtistListViewController: UIViewController{
let tableView = UITableView()
var safeArea: UILayoutGuide!
//var artists: [Artists]?
let textField = UITextField()
var searchTerm = "Search"
//var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
safeArea = view.safeAreaLayoutGuide
searchBar()
setUpTable()
setUpNavigation()
}
func searchBar(){
view.addSubview(textField)
textField.placeholder = "Search"
// not needed
//textField.frame = CGRect(x: 10,y: 200,width: 300.0,height: 30.0)
textField.borderStyle = UITextField.BorderStyle.line
textField.translatesAutoresizingMaskIntoConstraints = false
//Layout Configs
// constrain Top to safeArea Top
textField.topAnchor.constraint(equalTo: safeArea.topAnchor).isActive = true
textField.leftAnchor.constraint(equalTo: safeArea.leftAnchor).isActive = true
textField.rightAnchor.constraint(equalTo: safeArea.rightAnchor).isActive = true
// don't constrain the bottom
//textField.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
func setUpTable(){
view.addSubview(tableView)
// ArtistSearchModelData().loadArtists(searchTerm: "Adele"){ [weak self] (artists) in
// self?.artists = artists
//
// DispatchQueue.main.async{
// self?.tableView.reloadData()
// }
// }
//
// //populate with data
// tableView.delegate = self
// tableView.dataSource = self
// tableView.register(TableViewCell.self, forCellReuseIdentifier: "cell")
//turn off autoresizing
tableView.translatesAutoresizingMaskIntoConstraints = false
//Layout Configs
// constrain Top to textField Bottom
tableView.topAnchor.constraint(equalTo: textField.bottomAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: safeArea.leftAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: safeArea.rightAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor).isActive = true
}
func setUpNavigation(){
self.navigationItem.title = "Artists"
self.navigationController?.navigationBar.barTintColor = .white
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.titleTextAttributes = [
NSAttributedString.Key.foregroundColor: UIColor.orange,
NSAttributedString.Key.font: UIFont(name: "Arial-BoldMT", size: 30)
]
}
}
If you run that code as-is, you should get your Search textField above the (empty) tableView.
If you then un-comment your Artist-specific code, it should work properly.