I am having trouble displaying the data I got from my REST API. I can retrieve the data with no problem but the tableview is not displaying the data. How do I get the data inside the tableview cell in the tableview?
class SearchBSViewController: UIViewController {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var tableView: UITableView!
lazy var tapRecognizer: UITapGestureRecognizer = {
var recognizer = UITapGestureRecognizer(target:self, action: #selector(dismissKeyBoard))
return recognizer
}()
var searchResults: [Service] = []
let busStop = BusStop(odataMetadata: "", busStopCode: "", services: [])
let queryService = QueryService()
override func viewDidLoad() {
super.viewDidLoad()
alterLayout()
searchBar.delegate = self
}
func alterLayout() {
tableView.tableHeaderView = UIView()
tableView.estimatedSectionHeaderHeight = 50
navigationItem.titleView = searchBar
searchBar.showsScopeBar = false
searchBar.placeholder = "Search for bus stop by bus code"
}
}
extension SearchBSViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.searchResults.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell: BusCell = tableView.dequeueReusableCell(withIdentifier: "BusCell", for: indexPath) as? BusCell else {
return UITableViewCell()
}
let bus = searchResults[indexPath.row]
cell.busNoLbl.text = bus.serviceNo
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexpath: IndexPath) -> CGFloat {
return 100
}
}
extension SearchBSViewController: UISearchBarDelegate {
#objc func dismissKeyBoard() {
searchBar.resignFirstResponder()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
dismissKeyBoard()
print("Something")
guard let searchText = searchBar.text, !searchText.isEmpty else { return }
UIApplication.shared.isNetworkActivityIndicatorVisible = true
guard let searchNumber: Int = Int(searchText) else { return }
queryService.GetBusStop(BusNo: searchNumber) {
results in
UIApplication.shared.isNetworkActivityIndicatorVisible = false
if let results = results {
print(results.services?[1].nextBus?.estimatedArrival ?? 0)
self.searchResults = results.services!
self.tableView.reloadData()
self.tableView.setContentOffset(CGPoint.zero, animated: false)
}
}
}
func position(for bar: UIBarPositioning) -> UIBarPosition {
return .topAttached
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
view.addGestureRecognizer(tapRecognizer)
}
func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
view.removeGestureRecognizer(tapRecognizer)
}
}
class BusCell: UITableViewCell {
#IBOutlet weak var busNoLbl: UILabel!
#IBOutlet weak var firstBusLbl: UILabel!
#IBOutlet weak var secBusLbl: UILabel!
#IBOutlet weak var thirdBusLbl: UILabel!
#IBOutlet weak var firstPrg: UIProgressView!
#IBOutlet weak var secPrg: UIProgressView!
#IBOutlet weak var thirdPrg: UIProgressView!
#IBOutlet weak var firstType: UILabel!
#IBOutlet weak var secType: UILabel!
#IBOutlet weak var thirdType: UILabel!
func configure(services: Service) {
busNoLbl.text = services.serviceNo
firstBusLbl.text = services.nextBus?.estimatedArrival
secBusLbl.text = services.nextBus2?.estimatedArrival
thirdBusLbl.text = services.nextBus3?.estimatedArrival
}
}
class QueryService {
typealias QueryResult = (BusStop?) -> ()
var buses: BusStop = BusStop(odataMetadata: "", busStopCode: "", services: [])
let defaultSession = URLSession(configuration: .default)
var dataTask: URLSessionDataTask?
func GetBusStop(BusNo: Int, completionBlock: #escaping QueryResult){
dataTask?.cancel()
var urlComponents = URLComponents(string: "http://datamall2.mytransport.sg/ltaodataservice/BusArrivalv2")!
urlComponents.queryItems = [URLQueryItem(name: "BusStopCode", value: String(BusNo))]
guard let url = urlComponents.url else { return}
let urlRequest = Header(url: url) //input the header for authorization
dataTask = defaultSession.dataTask(with: urlRequest) { (data, response, error) in
if error != nil {
print(error!.localizedDescription)
}
guard let data = data else { return }
do {
let BusStopData = try
JSONDecoder().decode(BusStop.self, from: data)
DispatchQueue.main.async {
print("Queue")
completionBlock(BusStopData)
}
} catch let jsonError {
print(jsonError)
}
}
dataTask?.resume()
}
}
First thing is you need to set up a delegate and data source method for the table view. setup it in your view did load method
tableView.delegate = self
tableView.datasource = self
Second is you need to reload your table view after you hit your API call
tableView.reloadData()
Please set delegate and datasoruce of table view in alterLayout() function, like
tableView.delegate = self
tableView.datasource = self
Related
I want to pass the data from one view controller to another view controller when the user clicked the button . I am using button with delegate to pass the table view cell values into different view controller view . In second view controller I have two labels and one image to display the fields but the problem is when I clicked the button it is empty.
Here is the cell code .
import UIKit
protocol CellSubclassDelegate: AnyObject {
func buttonTapped(cell: MovieViewCell)
}
class MovieViewCell: UITableViewCell {
weak var delegate:CellSubclassDelegate?
static let identifier = "MovieViewCell"
#IBOutlet weak var movieImage: UIImageView!
#IBOutlet weak var movieTitle: UILabel!
#IBOutlet weak var movieOverview: UILabel!
#IBOutlet weak var someButton: UIButton!
#IBAction func someButtonTapped(_ sender: UIButton) {
self.delegate?.buttonTapped(cell: self)
}
override func prepareForReuse() {
super.prepareForReuse()
self.delegate = nil
}
func configureCell(title: String?, overview: String?, data: Data?) {
movieTitle.text = title
movieOverview.text = overview
if let imageData = data{
movieImage.image = UIImage(data: imageData)
// movieImage.image = nil
}
}
}
Here is the first view controller code .
import UIKit
class MovieViewController: UIViewController, UISearchBarDelegate {
#IBOutlet weak var userName: UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
private var presenter: MoviePresenter!
var finalname = ""
var movieTitle = ""
var movieOverview = ""
var movieImage : UIImage?
override func viewDidLoad() {
super.viewDidLoad()
userName.text = "Hello: " + finalname
setUpUI()
presenter = MoviePresenter(view: self)
searchBarText()
}
private func setUpUI() {
tableView.dataSource = self
tableView.delegate = self
}
private func searchBarText() {
searchBar.delegate = self
}
#IBAction func selectSegment(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0{
setUpUI()
presenter = MoviePresenter(view: self)
presenter.getMovies()
}
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText == ""{
presenter.getMovies()
}
else {
presenter.movies = presenter.movies.filter({ movies in
let originalTitle = movies.originalTitle.lowercased().range(of: searchText.lowercased())
let overview = movies.overview.lowercased().range(of: searchText.lowercased())
let posterPath = movies.posterPath.lowercased().range(of: searchText.lowercased())
return (originalTitle != nil) == true || (overview != nil) == true || (posterPath != nil) == true}
)
}
tableView.reloadData()
}
}
extension MovieViewController: MovieViewProtocol {
func resfreshTableView() {
tableView.reloadData()
}
func displayError(_ message: String) {
let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
let doneButton = UIAlertAction(title: "Done", style: .default, handler: nil)
alert.addAction(doneButton)
present(alert, animated: true, completion: nil)
}
}
extension MovieViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
presenter.rows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: MovieViewCell.identifier, for: indexPath) as! MovieViewCell
let row = indexPath.row
let title = presenter.getTitle(by: row)
let overview = presenter.getOverview(by: row)
let data = presenter.getImageData(by: row)
cell.delegate = self
cell.configureCell(title: title, overview: overview, data: data)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let dc = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as! MovieDeatilsViewController
let row = indexPath.row
dc.titlemovie = presenter.getTitle(by: row) ?? ""
dc.overview = presenter.getOverview(by: row) ?? ""
dc.imagemovie = UIImage(data: presenter.getImageData(by: row)!)
self.navigationController?.pushViewController(dc, animated: true)
}
}
extension MovieViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
extension MovieViewController : CellSubclassDelegate{
func buttonTapped(cell: MovieViewCell) {
guard (self.tableView.indexPath(for: cell) != nil) else {return}
let customViewController = storyboard?.instantiateViewController(withIdentifier: "MovieDeatilsViewController") as? MovieDeatilsViewController
customViewController?.titlemovie = movieTitle
customViewController?.imagemovie = movieImage
customViewController?.overview = movieOverview
self.navigationController?.pushViewController(customViewController!, animated: true)
}
}
Here is the details view controller code .
class MovieDeatilsViewController: UIViewController {
#IBOutlet weak var movieImage: UIImageView!
#IBOutlet weak var movieTitle: UILabel!
#IBOutlet weak var movieOverview: UILabel!
var titlemovie = ""
var overview = ""
var imagemovie :UIImage?
override func viewDidLoad() {
super.viewDidLoad()
movieTitle.text = titlemovie
movieOverview.text = overview
movieImage.image = imagemovie
}
}
Here is the result when I clicked the button .
The problem is you don't update you're global properties when selecting each of you're row,
If you pass data over cell delegate and pass you're cell through delegate, you can pass data from cell like:
customViewController?.titlemovie = cell.movieTitle.text ?? ""
customViewController?.imagemovie = cell.movieImage.image
customViewController?.overview = cell.movieOverview.text ?? ""
of course it would be better to pass you're data model to you're cell. and then share that through you're delegate not share you're cell, like:
protocol CellSubclassDelegate: AnyObject {
func buttonTapped(cell: MovieModel)
}
I want to add restaurant category search functionality to RestaurantTableViewController which use yelp api business data. I followed basic search bar in table view tutorials but I do not do for my specific scenario. I do not differ filtered data and not filtered data in my RestaurantTableViewController when the search is active.
RestaurantTableViewController is below:
import UIKit
import CoreLocation
protocol ListActions: class {
func didTapCell(_ viewController: UIViewController, viewModel: RestaurantListViewModel)
}
class RestaurantTableViewController: UIViewController, UITableViewDelegate, FiltersViewControllerDelegate {
#IBOutlet weak var yourLocationLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
private let locationManager = CLLocationManager()
private let locationService = LocationService()
var filteredData: [RestaurantListViewModel]!
let appDelegate = UIApplication.shared.delegate as? AppDelegate
var viewModels = [RestaurantListViewModel]() {
didSet {
DispatchQueue.main.async {
// this no more loading, i notice it load late that is why when reload data in table view not working
}
}
}
weak var delegate: ListActions?
override func viewDidLoad() {
super.viewDidLoad()
filteredData = appDelegate!.data
userCurrentLocation()
DispatchQueue.main.async {
self.tabBarController?.tabBar.isHidden = false
}
if appDelegate?.data?.count == 0 {
tableView.setEmptyView(title: "There are no restaurants in your current location.", message: "Please change your location and try again!")
}
tableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
if appDelegate?.data?.count == 0 {
tableView.setEmptyView(title: "There are no restaurants in your current location.", message: "Please change your location and try again!")
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("did appear")
self.removeActivityIndicator()
tableView.reloadData()
tableView.dataSource = self
tableView.delegate = self
DispatchQueue.main.async {
self.tabBarController?.tabBar.isHidden = false
}
}
}
extension RestaurantTableViewController: UITableViewDataSource {
// MARK: - Table view data source
func collectionSkeletonView(_ skeletonView: UITableView, cellIdentifierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier {
return "RestaurantCell"
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("number of rows \(String(describing: viewModels.count))")
print(viewModels)
if appDelegate?.data?.count == 0 {
self.tableView.setEmptyView(title: "There are no restaurants in your current location.", message: "Please change your location and try again!")
}
if (self.searchBar.isUserInteractionEnabled) {
return self.filteredData.count
}
else {
return appDelegate!.data?.count ?? 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RestaurantCell", for: indexPath) as! RestaurantTableViewCell
if (self.searchBar.isUserInteractionEnabled) {
let vm = filteredData?[indexPath.row]
cell.configure(with: vm!)
return cell
} else {
let vm = appDelegate!.data?[indexPath.row]
cell.configure(with: vm!)
return cell
}
}
// MARK: - Delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let detailsViewController = storyboard?.instantiateViewController(withIdentifier: "DetailsViewController")
else {return}
navigationController?.pushViewController(detailsViewController, animated: true)
let vm = appDelegate!.data?[indexPath.row]
appDelegate!.didTapCell(detailsViewController, viewModel: vm!)
if let selectedRowIndexPath = self.tableView.indexPathForSelectedRow {
self.tableView.deselectRow(at: selectedRowIndexPath, animated: true)
}
}
}
extension RestaurantTableViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = searchText.isEmpty ? appDelegate?.data : appDelegate?.data?.filter { (item: RestaurantListViewModel) -> Bool in
return item.categories[0].title.range(of: searchText, options: .caseInsensitive, range: nil, locale: nil) != nil
}
tableView.reloadData()
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.searchBar.showsCancelButton = true
}
}
My RestaurantTableViewCell data is below and I am getting restaurant table view cell data in configure function. But in RestaurantTableViewController's cellForRow method I do not differ my filtered and normal data when search is active.
class RestaurantTableViewCell: UITableViewCell {
#IBOutlet weak var cardContainerView: ShadowView!
#IBOutlet weak var restaurantImageView: UIImageView!
#IBOutlet weak var makerImageView: UIImageView!
#IBOutlet weak var restaurantNameLabel: UILabel!
#IBOutlet weak var locationLabel: UILabel!
#IBOutlet weak var restaurantType: UILabel!
let cornerRadius : CGFloat = 10.0
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
cardContainerView.layer.cornerRadius = cornerRadius
func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
cardContainerView.layer.shadowColor = UIColor.gray.cgColor
cardContainerView.layer.shadowOffset = CGSize(width: 5.0, height: 5.0)
cardContainerView.layer.shadowRadius = 15.0
cardContainerView.layer.shadowOpacity = 0.9
restaurantImageView.layer.cornerRadius = cornerRadius
restaurantImageView.clipsToBounds = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func configure(with viewModel: RestaurantListViewModel) {
// For background thread
DispatchQueue.global(qos: .background).async {
DispatchQueue.main.async {
self.restaurantImageView.af_setImage(withURL: viewModel.imageUrl)
self.restaurantNameLabel.text = viewModel.name
self.locationLabel.text = "\(viewModel.formattedDistance) m"
}
}
if let restaurantType: String = String(viewModel.categories[0].title) {
self.restaurantType.text = restaurantType
}
}
}
RestaurantListViewModel is below also:
struct Business: Codable {
let id: String
let name: String
let imageUrl: URL
let distance: Double
let categories: [Category]
}
struct RestaurantListViewModel {
let name: String
let imageUrl: URL
let distance: Double
let id: String
let categories: [Category]
}
extension RestaurantListViewModel {
init(business: Business) {
self.name = business.name
self.id = business.id
self.imageUrl = business.imageUrl
self.distance = business.distance
self.categories = business.categories
}
}
I am new to swift programming and would need some help to check what is wrong in my tableviewcell. I have tried alot of great suggestions on stackoverflow.( make sure your outlets are connected, set delegate and datasource of your tableview to self)
This is my ViewController:
import UIKit
class CharacterViewController: UIViewController, UITableViewDataSource, UITableViewDelegate , APIControllerProtocol {
#IBOutlet weak var CharacterInfoView: UITableView!
var apiController:APIController!
var dataArray: [[String:Any]]?
var processcharacter= [CharacterListModel]()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor=UIColor.white
self.CharacterInfoView.estimatedRowHeight = 44
self.CharacterInfoView.rowHeight = UITableViewAutomaticDimension
self.CharacterInfoView.dataSource = self
self.CharacterInfoView.delegate = self
apiController = APIController()
apiController.delegate=self
self.navigationItem.title = "Character"
self.view.showLoading()
apiController.getCharacterData{ (statusCode, data, response, error) -> () in
self.view.stopLoading()
if(statusCode == nil)
{
self.view.showServiceNotAvailableMessage(self)
}
if !(error == nil)
{
self.view.showServiceNotAvailableMessage(self)
}
if statusCode == 200
{
do
{
self.processcharacter= CharacterListData.processData(data: data)
self.CharacterInfoView.reloadData()
}
catch(_ as NSError)
{
}
}
else
{
return
}
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.dataArray == nil
{
return 0
}
else
{
return processcharacter.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"Cell", for:indexPath) as! CharacterTableViewCell
var processcharacters= processcharacter[indexPath.row]
cell.location.text = processcharacters.location
cell.name.text = processcharacters.name
cell.characterID.text = processcharacters.characterID
cell.time.text = processcharacters.lastlocatedtime
if wecares.sos == true {
processcharacters.imagebutton = UIImage(named: "sos_icon")!
}
else{
processcharacters.imagebutton = UIImage(named: "null_button")!
}
cell.button.image = processcharacters.imagebutton
return cell
}
func reachabilityChanged(_ status: Bool) {
}
}
This is my subclass for my ViewController:
import Foundation
class CharacterListDataHelper: NSObject {
static func processData(data: AnyObject?) -> [CharacterListModel]
{
var modelList:[CharacterListModel] = [CharacterListModel]()
let darr = try? JSONSerialization.jsonObject(with: data! as! Data, options: .mutableLeaves) as! [[String:Any]]
var dataModel:CharacterListModel
for obj in darr!
{
dataModel = CharacterListModel()
dataModel.location = obj["playerLocation"] as! String
dataModel.name = obj["playerName"] as! String
dataModel.characterID= obj["playerID"] as! String
dataModel.lastlocatedtime = obj["lastUpdatedTime"] as! String
}
modelList.append(dataModel)
}
return modelList
}
}
This is my Model:
import Foundation
struct CharacterListModel {
var name: String?
var characterID: String?
var location: String?
var lastlocatedtime: String?
var imagebutton: UIImage?
var sos: Bool?
}
This is my TableViewCell:
class CharacterTableViewCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var characterID: UILabel!
#IBOutlet weak var location: UILabel!
#IBOutlet weak var lastlocatedtime: UILabel!
#IBOutlet weak var button: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
Thanks in advance!
Don't fetch data in viewDidLoad() method. Fetch in viewWillAppear and reload after getting data.
I have a problem. I need that when I press a button this will automatically refresh my page putting inside it the new content. Possibly while this happens, I would like the button to do a circle animation. Thanks in advance.
class ViewControllerAvvisi: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate
{
var selfTable: NSMutableArray = NSMutableArray()
#IBOutlet weak var MessageTable: UITableView!
#IBOutlet weak var MessageTextField: UITextField!
#IBOutlet weak var SendMessage: UIButton!
var messagesArray:[String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.MessageTable.delegate = self
self.MessageTable.dataSource = self
self.MessageTable.delegate = self
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "TableViewTapped")
self.MessageTable.addGestureRecognizer(tapGesture)
func retrieveMessages() {
let query = PFQuery(className: "Message")
query.findObjectsInBackgroundWithBlock {
(remoteObjects: [PFObject]?, error: NSError?) -> Void in
self.messagesArray = [String]()
for messageObject in remoteObjects! {
let messageText: String? = (messageObject as PFObject) ["Text"] as? String
if messageText != nil {
self.messagesArray.append(messageText!)
}
}
self.MessageTable.reloadData()
}
}
retrieveMessages()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.MessageTable.dequeueReusableCellWithIdentifier("MessageCell")! as UITableViewCell
cell.textLabel?.text = self.messagesArray[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messagesArray.count
}
#IBAction func SendMessage(sender: AnyObject) {
self.MessageTable.endEditing(true)
let NewMessage: PFObject = PFObject (className: "Message")
NewMessage["Text"] = self.MessageTextField.text
self.MessageTextField.enabled = false
self.SendMessage.enabled = false
NewMessage.saveInBackgroundWithBlock { (success:Bool, NSError) -> Void in
if (success == true) {
NSLog("Message successfully saved")
}else{
NSLog("Message didn't save")
}
self.MessageTextField.enabled = true
self.SendMessage.enabled = true
self.MessageTextField.text = ""
}
}
#IBAction func Refresh(sender: AnyObject) {
}
}
Just use the function you created to reload the new data. Move it outside of the viewDidLoad function.
Add an IBAction with the button you want to reload data and add retrieveMessages(). As you reload, new data will automatically be loaded.
#IBAction func refreshData(sender: AnyObject) {
retrieveMessages()
}
For the circle animation, I recommend using a UIActivityIndicatorView.
I'm trying to send a request to search for movies, but when i tap on the search bar to write the text i get a crash in cellforrow and it's not calling numberofrows neither the request. Here's my code so far:
class InTheaters: UITableViewController, UISearchResultsUpdating, UISearchBarDelegate {
#IBOutlet weak var poster: UIImageView!
#IBOutlet weak var movieTitle: UILabel!
#IBOutlet weak var date: UILabel!
#IBOutlet weak var duration: UILabel!
#IBOutlet weak var rating: UILabel!
#IBOutlet var theatersTable: UITableView!
#IBOutlet weak var starsView: CosmosView!
var results = [Movie]()
var searchResults = [Search]()
var resultSearchController: UISearchController!
private let key = "qtqep7qydngcc7grk4r4hyd9"
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.resultSearchController.searchBar.sizeToFit()
self.resultSearchController.searchBar.placeholder = "Search for movies"
self.theatersTable.tableHeaderView = self.resultSearchController.searchBar
self.theatersTable.reloadData()
getMovieInfo()
customIndicator()
infiniteScroll()
}
func customIndicator() {
self.theatersTable.infiniteScrollIndicatorView = CustomInfiniteIndicator(frame: CGRectMake(0, 0, 24, 24))
self.theatersTable.infiniteScrollIndicatorMargin = 40
}
func infiniteScroll() {
self.theatersTable.infiniteScrollIndicatorStyle = .White
self.theatersTable.addInfiniteScrollWithHandler { (scrollView) -> Void in
self.getMovieInfo()
}
}
func getMovieInfo() {
Alamofire.request(.GET, "http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json?page_limit=10&page=1&country=us&apikey=\(key)").responseJSON() {
(responseData) -> Void in
if let swiftyResponse = responseData.result.value {
let movies = Movies(JSONDecoder(swiftyResponse))
for movie in movies.allMovies {
self.results.append(movie)
}
}
self.theatersTable.reloadData()
self.theatersTable.finishInfiniteScroll()
}
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
self.searchResults.removeAll(keepCapacity: false)
if (searchController.searchBar.text?.characters.count > 0) {
Alamofire.request(.GET, "http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=N&page_limit=10&page=1&apikey=\(key)").responseJSON() {
(responseData) -> Void in
print(responseData)
if let swiftyResponse = responseData.result.value {
let searches = Searches(JSONDecoder(swiftyResponse))
for search in searches.allSearches {
self.searchResults.append(search)
}
}
self.theatersTable.reloadData()
self.theatersTable.finishInfiniteScroll()
}
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.resultSearchController.active) {
return self.searchResults.count
} else {
return self.results.count
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
let titleLabel = cell.viewWithTag(1) as! UILabel
let yearLabel = cell.viewWithTag(2) as! UILabel
let durationLabel = cell.viewWithTag(3) as! UILabel
let posterImage = cell.viewWithTag(5) as! UIImageView
let starsTag = cell.viewWithTag(6) as! CosmosView
if (self.resultSearchController.active) {
titleLabel.text = searchResults[indexPath.row].titleMovie
yearLabel.text = searchResults[indexPath.row].yearMovie
durationLabel.text = searchResults[indexPath.row].durationMovie?.description
posterImage.sd_setImageWithURL(NSURL(string: searchResults[indexPath.row].posterMovie!))
starsTag.rating = searchResults[indexPath.row].ratingMovie!
starsTag.settings.updateOnTouch = false
} else {
titleLabel.text = results[indexPath.row].titleMovie
yearLabel.text = results[indexPath.row].yearMovie
durationLabel.text = results[indexPath.row].durationMovie?.description
posterImage.sd_setImageWithURL(NSURL(string: results[indexPath.row].posterMovie!))
starsTag.rating = results[indexPath.row].ratingMovie!
starsTag.settings.updateOnTouch = false
}
return cell
}
I also have some structs with information for the request tell me if you need something from that too.
Found the answer should have reloadData before the request.
func updateSearchResultsForSearchController(searchController: UISearchController) {
self.searchResults.removeAll(keepCapacity: false)
self.theatersTable.reloadData()//should have added this before the request
if (searchController.searchBar.text?.characters.count > 0) {
Alamofire.request(.GET, "http://api.rottentomatoes.com/api/public/v1.0/movies.json?q=\(searchController.searchBar.text!)&page_limit=10&page=1&apikey=\(key)").responseJSON() {
(responseData) -> Void in
if let swiftyResponse = responseData.result.value {
let searches = Searches(JSONDecoder(swiftyResponse))
for search in searches.allSearches {
self.searchResults.append(search)
}
}
self.theatersTable.reloadData()
self.theatersTable.finishInfiniteScroll()
}
}
}