I get array index out of range - swift

when I output the test result in my application, I get
fatal error: array index out of range
In the code I marked the place where the error occurred. What could be the cause of the error?
import UIKit
import RealmSwift
class ResultVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var message = ""
var result = 0
var testedVerbs = [Verb]()
var repeatTestedVerbs = [Verb]()
#IBOutlet weak var resultLabel:UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var repeatVerbs: UILabel!
#IBOutlet weak var nextButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
tableView.reloadData()
setUp()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return testedVerbs.isEmpty ? 0 : testedVerbs.count
}
private func setUp() {
nextButton.setUpButton(button: nextButton, color: white, tintColor: black, cornerRadius: 12)
for verb in testedVerbs {
if verb.progress <= 0.49 {
repeatTestedVerbs.append(verb)
}
}
if repeatTestedVerbs.count <= 3 {//testedVerbs.count/20 * 100 {
view.backgroundColor = orange
message = "You Can Do Better!"
} else {
view.backgroundColor = green
message = "Good Job!"
}
resultLabel.text = "\(message) \(result) / \(testedVerbs.count)"
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.backgroundColor = .clear
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! ResultCell
// MARK: Index out of range
let verb = repeatTestedVerbs[indexPath.row]
cell.infinitiv.text = verb.infinitiv
cell.translate.text = verb.translate
cell.level.text = verb.level
cell.backgroundColor = .clear
return cell
}
static func storyboardInstance() -> ResultVC? {
let storyboard = UIStoryboard(name: String(describing: self), bundle: nil)
return storyboard.instantiateInitialViewController() as? ResultVC
}
#IBAction func repeatButton(_ sender: UIButton) {
if let nvc = navigationController {
nvc.popViewController(animated: true)
}
}
#IBAction func cancel(_ sender:UIButton) {
if let nvc = navigationController {
for vc in nvc.viewControllers {
if vc is ThemeTVC {
navigationController?.popToViewController(vc, animated: true)
break
}
}
}
}
}

Your numberOfRows is based on testedVerbs, but your cellForRowAt reads from repeatTestedVerbs.

Related

Label.text Error! - Unexpectedly found nil while implicitly unwrapping an Optional value

I am new to iOS development and I found an error that I can not get past. I have read a lot online and on Stackoverflow but I don't understand why this error keeps coming up.
Upon testing and doing breakpoints I think I was able to get the data needed problem is when I display it on screen wit uilabel.
import UIKit
class ArtistViewController: UIViewController, artistViewModelDelegate {
#IBOutlet weak var artwork: UIImageView!
#IBOutlet weak var artistName: UILabel!
#IBOutlet weak var albumName: UILabel!
func loadArtistViewModel(data: ArtistViewModel) {
guard let artistData = data as? ArtistViewModel else {}
artistName.text = artistData.artistName //Unexpectedly found nil while unwrapping an Optional value
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Hope you guys can help me on this one, Thank you so much!
EDIT
ViewController where the instance of ArtistViewController gets called
import UIKit
import Alamofire
import SwiftyJSON
protocol artistViewModelDelegate {
func loadArtistViewModel(data: ArtistViewModel)
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, artistSearchDelegate {
#IBOutlet weak var tableView: UITableView!
var data: [ArtistItem] = []
var delegate: artistViewModelDelegate?
var artistViewModel: ArtistViewModel?
var params = [API_CONSTANTS.URL_TYPES.PARAMETERS.TERM: "Maroon 5",API_CONSTANTS.URL_TYPES.PARAMETERS.COUNTRY: API_CONSTANTS.AU, API_CONSTANTS.URL_TYPES.PARAMETERS.MEDIA: API_CONSTANTS.URL_TYPES.PARAMETERS.MUSIC]
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = ArtistViewController()
getItunesData()
tableView.dataSource = self
tableView.delegate = self
tableView.register(UINib(nibName: "artistCell", bundle: nil), forCellReuseIdentifier: "artistCell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "artistCell", for: indexPath) as! artistCell
cell.artistName.text = data[indexPath.row].artistName
cell.albumName.text = data[indexPath.row].albumName
cell.genre.text = data[indexPath.row].genre
cell.trackPrice.text = "$\(String(data[indexPath.row].trackPrice))"
cell.albumArtwork.load(url: data[indexPath.row].artwork)
cell.layer.cornerRadius = 5
cell.layer.masksToBounds = true
return cell
}
//Mark: To Artist ViewController
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
artistViewModel = ArtistViewModel(artist: data[indexPath.row])
let artistViewController = storyboard?.instantiateViewController(withIdentifier: "ArtistViewController") as! ArtistViewController
delegate?.loadArtistViewModel(data: artistViewModel!)
self.navigationController?.pushViewController(artistViewController, animated: true)
}
func getItunesData(){
Alamofire.request(API_CONSTANTS.URL_TYPES.URL, method: .get, parameters: params).responseJSON
{ response in
if response.result.isSuccess {
let json = JSON(response.result.value)
self.data = ArtistModel(json: json).artistItems
self.tableView.reloadData()
} else {
}
}
}
func didTapSearch(artist: String) {
params = [API_CONSTANTS.URL_TYPES.PARAMETERS.TERM:"\(artist)"]
getItunesData()
}
#IBAction func searchButton(_ sender: Any) {
let popupSearchVC = storyboard?.instantiateViewController(withIdentifier: "popupSearchView") as! PopupViewController
popupSearchVC.delegate = self
present(popupSearchVC, animated: true, completion: nil)
}
}
The problem is the protocol. You set delegate to an instance which is not the instance in the storyboard.
But with the given code you don't need the protocol at all.
Delete
protocol artistViewModelDelegate {
func loadArtistViewModel(data: ArtistViewModel)
}
...
var delegate: artistViewModelDelegate?
...
self.delegate = ArtistViewController()
and the protocol conformance, then replace
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
artistViewModel = ArtistViewModel(artist: data[indexPath.row])
let artistViewController = storyboard?.instantiateViewController(withIdentifier: "ArtistViewController") as! ArtistViewController
delegate?.loadArtistViewModel(data: artistViewModel!)
self.navigationController?.pushViewController(artistViewController, animated: true)
}
with
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let artistViewController = storyboard?.instantiateViewController(withIdentifier: "ArtistViewController") as! ArtistViewController
artistViewController.artistViewModel = ArtistViewModel(artist: data[indexPath.row])
self.navigationController?.pushViewController(artistViewController, animated: true)
}
And in ArtistViewController you have to use a temporary variable for the model because the outlets are not connected (yet) right after instantiation.
Replace the code in the question with
import UIKit
class ArtistViewController: UIViewController, artistViewModelDelegate {
#IBOutlet weak var artwork: UIImageView!
#IBOutlet weak var artistName: UILabel!
#IBOutlet weak var albumName: UILabel!
var artistViewModel : ArtistViewModel!
override func viewDidLoad() {
super.viewDidLoad()
artistName.text = artistViewModel.artistName
}
}

Why is the data in the collection view cells gets changing when I scroll the table view or the collection view?

I am trying to embed the collection view in the table view. When the page gets loaded I will retrieve the data field by field from the database and reloads the data whenever I retrieve the single field from the database. Here while reloading the table view I need to check the value i.e "oneimage" so if that value is not empty it should set to the collection view cell. The problem is whenever I scroll the table view the data in the collection view cells get swapped. Here is the code below
import UIKit
import Firebase
import FirebaseFirestore
import FirebaseAuth
import SDWebImage
struct values {
var quesvalue: String
var answvalue: String
var ImageUrl = [String]()
}
class QuestionsCell: UITableViewCell,UICollectionViewDelegate {
#IBOutlet weak var collectionview: UICollectionView!
#IBOutlet weak var card: UIView!
#IBOutlet weak var question: UILabel!
#IBOutlet weak var answer: UILabel!
#IBOutlet weak var speakbutton: UIButton!
#IBOutlet weak var collectionviewh: NSLayoutConstraint!
var imageArray = [String] ()
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
extension QuestionsCell {
func setCollectionViewDataSourceDelegate<D: UICollectionViewDataSource &
UICollectionViewDelegate>(dataSourceDelegate: D, forRow row: Int) {
collectionview.delegate = dataSourceDelegate
collectionview.dataSource = dataSourceDelegate
print("collectionviee.tag",collectionview.tag,row)
collectionview.tag = row
collectionview.contentOffset = .zero // Stops collection view if it was scrolling.
}
}
class CollectionViewCell: UICollectionViewCell{
#IBOutlet weak var backcard: UIView!
#IBOutlet weak var imageview: UIImageView!
var task: URLSessionDataTask?
override func awakeFromNib() {
super.awakeFromNib()
}
override func prepareForReuse(){
imageview.image = nil
}
}
class ViewController: UIViewController ,UITableViewDelegate,
UITableViewDataSource,UICollectionViewDataSource,UICollectionViewDelegate {
#IBOutlet weak var tableview: UITableView!
var JSONArray = [String:Any]()
var quesArray = [String]()
var ansArray = [String]()
var answer : String!
var imagesarray = [String]()
var open : [values] = []
var oneimage = [String]()
var storedOffsets = [Int: CGFloat]()
override func viewDidLoad() {
super.viewDidLoad()
tableview.dataSource = self
tableview.delegate = self
tableview.rowHeight=UITableView.automaticDimension
tableview.estimatedRowHeight=150
Firestore.firestore().collection("User").document("7ngPwZin2wg7j5JZtI0hKJO8uSA2").collection("Popop").document("7ngPwZin2wg7j5JZtI0hKJO8uSA2").collection("Answers").document("Earlyyears").getDocument() { (document, error) in
if let document = document, document.exists {
self.open.removeAll()
self.imagesarray.removeAll()
self.oneimage.removeAll()
if let b1 = document.data()!["Name"] as? [String: Any] {
print("1",b1)
if let firstName = b1["Answer"] as? String {
print("firstName is",firstName)
if firstName != "No answer recorded"{
self.answer = firstName
self.ansArray.append(firstName)
if let imageurlarray = b1["ImageURL"] as? [String] {
self.imagesarray = imageurlarray
print("imageurl array in meaning feild is",imageurlarray)
self.open.insert(values(quesvalue: self.quesArray[0],answvalue: self.answer,ImageUrl: self.imagesarray), at: 0)
self.tableview.reloadData()
}
}
}
}
if let b2 = document.data()!["Meaning"] as? [String: Any] {
print("1")
if let firstName = b2["Answer"] as? String {
print("firstName is",firstName)
if firstName != "No answer recorded"{
self.answer = firstName
self.ansArray.append(firstName)
if let imageurlarray = b2["ImageURL"] as? [String] {
self.imagesarray = imageurlarray
print("imageurl array in meaning feild is",imageurlarray)
self.open.insert(values(quesvalue: self.quesArray[1],answvalue: self.answer,ImageUrl: self.imagesarray), at: 1)
self.tableview.reloadData()
}
}
}
}
} else {
print("Document does not exist")
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("ansArry.count is",open.count)
return open.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("entered into cellfor row at")
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! QuestionsCell
print("quesrray,ansArray are",quesArray,ansArray,open)
if open.count > indexPath.row{
cell.question.text = open[indexPath.row].quesvalue
cell.answer.text = open[indexPath.row].answvalue
print("cell.ques.text",cell.question.text)
oneimage = open[indexPath.row].ImageUrl
print("onimage before checking",oneimage)
if !oneimage.isEmpty{
print("entered into oneimage not empty",oneimage)
cell.collectionview.isHidden = false
cell.collectionviewh.constant = 160
cell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: indexPath.row)
}
else{
print("dont show collection view")
cell.collectionview.isHidden = true
cell.collectionviewh.constant = 0
}
}
else{
print("<")
}
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print("imagesarray.count is",oneimage.count)
print("oneimage.count")
return oneimage.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell: CollectionViewCell = (collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionCell", for: indexPath) as? CollectionViewCell)!
if oneimage.count > indexPath.row{
if oneimage != [""] {
let image = oneimage[indexPath.row]
print("oneimage is",image)
print("entered into oneimage not empty")
cell.imageview.sd_setImage(with: URL(string: image))
}
}
return cell
}
Here are the screenshots of my output.
As I mentioned in the comments, this is because of the reusability. That means when a cell goes out from bottom/top, the same cell (containing the previous setup) comes in from top/bottom. So if you set something async, like a remote image on it, it may be visible on incorrect cell. You should make sure you are selecting correct cell when you are about to set the image on it.
For example you should change this:
cell.imageview.sd_setImage(with: URL(string: image))
to something like this:
(collectionView.cellForItem(at: indexPath) as? CollectionViewCell)?.imageview.sd_setImage(with: URL(string: image))
This will ask the collectionView for the real cell instead of the reused one. I don't know how sd library works, but you may want to do this in the completionHandler of the library.
Maybe this article could help you.

Google Places Autocomplete API Does not Populate the exact address in my Tableview

I am using google Place Autocomplete API, i have the UITextField instead of UISearchBar with the same functionality; I am having the search estimates to be populated in a tableView. However, the results dont show the exact address; instead it only shows name of places. How can I make it so the results in the tableview are the exact address instead of places name?
Here is my code:
class DeliveryAddressVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var streetTextField: UITextField!
#IBAction func searchTextClicked(_ sender: Any) {}
#IBOutlet weak var tableView: UITableView!
var tableData=[String]()
var fetcher: GMSAutocompleteFetcher?
override func viewDidLoad() {
super.viewDidLoad()
if streetTextField.text == "" {
tableView.isHidden = true
}
self.edgesForExtendedLayout = []
// Set bounds to inner-west Sydney Australia.
let neBoundsCorner = CLLocationCoordinate2D(latitude: -33.843366,
longitude: 151.134002)
let swBoundsCorner = CLLocationCoordinate2D(latitude: -33.875725,
longitude: 151.200349)
let bounds = GMSCoordinateBounds(coordinate: neBoundsCorner,
coordinate: swBoundsCorner)
// Set up the autocomplete filter.
let filter = GMSAutocompleteFilter()
filter.type = .establishment
// Create the fetcher.
fetcher = GMSAutocompleteFetcher(bounds: bounds, filter: filter)
fetcher?.delegate = self as GMSAutocompleteFetcherDelegate
streetTextField.addTarget(self, action: #selector(DeliveryAddressVC.textFieldDidChanged(_:)), for: UIControl.Event.editingChanged)
tableView.delegate = self
tableView.dataSource = self
tableView.reloadData()
}
// MARK: -UITextField Action
#objc func textFieldDidChanged(_ textField:UITextField ){
if streetTextField.text == "" {
tableView.isHidden = true
}else {
tableView.isHidden = false
}
fetcher?.sourceTextHasChanged(streetTextField.text!)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var section = indexPath.section
var row = indexPath.row
let cell: UITableViewCell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier:"addCategoryCell")
cell.selectionStyle = UITableViewCell.SelectionStyle.none
cell.backgroundColor = UIColor.clear
cell.contentView.backgroundColor = UIColor.clear
cell.textLabel?.textAlignment = NSTextAlignment.left
cell.textLabel?.textColor = UIColor.black
cell.textLabel?.font = UIFont.systemFont(ofSize: 14.0)
cell.textLabel?.text = tableData[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.isHidden = true
}
}
extension DeliveryAddressVC: GMSAutocompleteFetcherDelegate {
func didAutocomplete(with predictions: [GMSAutocompletePrediction]) {
tableData.removeAll()
for prediction in predictions {
tableData.append(prediction.attributedPrimaryText.string)
//print("\n",prediction.attributedFullText.string)
//print("\n",prediction.attributedPrimaryText.string)
//print("\n********")
}
tableView.reloadData()
}
func didFailAutocompleteWithError(_ error: Error) {
print(error.localizedDescription)
}
}
Found the solution; I had to change two lines in my code:
Changed this:
filter.type = .establishment
To: filter.type = .address
AND
This: tableData.append(prediction.attributedPrimaryText.string)
To: tableData.append(prediction.attributedFullText.string)

how to search data from model in swift?

I want to search for some data in the table view using the search bar, but when I try to find data in my model, I'm not able to search that data.I made a expand table view cell and created a search bar for searching data, but still I can't search the data in the model. How can I achieve that?
here is my code:
import UIKit
class FAQViewController: UIViewController, UITableViewDataSource {
var dataFaq = [modelFAQ]()
let items = [
modelFAQ(name: "1. search box", description: "The design led users to instinctively search for their question first before clicking the FAQs"),
modelFAQ(name: "2.list of FAQs ", description: "Customers clicked around on the FAQs first."),
modelFAQ(name: "3. customers", description: "top issues first and then use the search for the questions instead of browsing and yielding more relevant results")
]
#IBOutlet fileprivate weak var tableView: UITableView!
#IBOutlet weak var searchDataBar: UISearchBar!
fileprivate var indexPaths: Set<IndexPath> = []
var cellIdentifier = "dataSourceFAQ"
var searchData = [String]()
var searching = false
override var preferredStatusBarStyle: UIStatusBarStyle{
return .lightContent
}
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
searchDataBar.delegate = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if searching {
return searchData.count
}else {
return items.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! FAQTableViewCell
if searching{
cell.titleLabel.text = searchData[indexPath.row]
}else{
cell.titleLabel.text = items[indexPath.row].name
}
let nameDetail = self[indexPath].name as? String
let description = self[indexPath].description
cell.update(name: nameDetail ?? "0", description: description)
cell.state = cellIsExpanded(at: indexPath) ? .expanded : .collapsed
return cell
}
override func viewWillAppear(_ animated: Bool) {
tabBarController?.tabBar.isHidden = true
}
private func setupTableView(){
tableView.delegate = self
tableView.dataSource = self
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 200.0
tableView.separatorStyle = .none
}
}
extension FAQViewController: UITableViewDelegate{
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as!FAQTableViewCell
cell.state = .expanded
self.addExpandedIndexPath(indexPath)
tableView.beginUpdates()
tableView.endUpdates()
print("1")
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! FAQTableViewCell
cell.state = .collapsed
self.removeExpandedIndexPath(indexPath)
tableView.beginUpdates()
tableView.endUpdates()
print("2")
}
}
extension FAQViewController {
func cellIsExpanded(at indexPath: IndexPath) -> Bool {
return indexPaths.contains(indexPath)
}
func addExpandedIndexPath(_ indexPath: IndexPath) {
indexPaths.insert(indexPath)
}
func removeExpandedIndexPath(_ indexPath: IndexPath) {
indexPaths.remove(indexPath)
}
}
extension FAQViewController {
subscript(indexPath: IndexPath) -> modelFAQ {
return items[indexPath.row]
}
}
extension FAQViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchData = searchText.isEmpty ? items: items.filter{ $0.name(searchText)}
searching = true
tableView.reloadData()
}
}
here is my table view cell
import UIKit
class FAQTableViewCell: UITableViewCell {
enum cellState{
case collapsed
case expanded
var carretImage: UIImage {
switch self {
case .collapsed:
return UIImage(named: "ic_arrow_down")!
case .expanded:
return UIImage(named: "ic_arrow_up")!
}
}
}
#IBOutlet private weak var stackView: UIStackView!
#IBOutlet private weak var containerView: UIView!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet private weak var carret: UIImageView!
#IBOutlet private weak var descriptionLabel: UILabel!
private let expandedViewIndex: Int = 1
var state: cellState = .expanded {
didSet{
toggle()
}
}
override func awakeFromNib() {
selectionStyle = .none
containerView.layer.cornerRadius = 5.0
}
private func toggle(){
stackView.arrangedSubviews[expandedViewIndex].isHidden = stateIsCollapsed()
carret.image = state.carretImage
}
private func stateIsCollapsed() -> Bool{
return state == .collapsed
}
func update(name: String, description: String){
titleLabel.text = name
descriptionLabel.text = description
}
}
here is my model
struct modelFAQ {
var name: String
var description: String
}
Two issues:
You have to declare searchData as the same type as the main data.
By the way according to the naming convention struct and class names start with a capital letter
var searchData = [ModelFAQ]()
The search filter closure is wrong. Write
searchData = searchText.isEmpty ? items : items.filter{ $0.name.contains(searchText)}
or if you want to search case insensitive
searchData = searchText.isEmpty ? items : items.filter{ $0.name.range(of: searchText, options: .caseInsensitive) != nil }
And you have to change in cellForRowAt
cell.titleLabel.text = searchData[indexPath.row].name
NOTE: Always start class/struct name with CAPITAL LETTER
Wrong: modelFAQ
correct: ModelFAQ
You have made one mistake, you have to declare your searchData Array like below
var searchData = [ModelFAQ]()
and while in datasource method you have to get name from the ModelFAQ object and assign it to your label.
Hope it will help you.

Swift - Tableview Cells Stay Highlighted - Except for Top One - No Matter What

So I'm new to swift and I've been having some problems getting all of my tableview cells to deselect after performing the segue. Right now all of the cells stay highlighted after I perform the segue, except the top one. The top one is selectable too and performs the segue, but it has no highlighting at all.
This is strange behavior but I have tried all of the basics.
I've tried
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
I've tried
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let selectionIndexPath = self.tableView.indexPathForSelectedRow {
self.tableView.deselectRow(at: selectionIndexPath, animated: animated)
}
}
I've also tried it in the prepare for segue method.
I've also tried it from the cell: cell.selectionStyle = .none
I've also tried changing "selection" in the story board to none.
Nothing seems to change the behavior so I'm at a loss. I think I've messed up something somewhere and can't find what it is.
Here is my tableview class in its entirety if anyone wants to take a look.
import UIKit
import Firebase
class DraftListCell : UITableViewCell {
#IBOutlet weak var playerName: UILabel!
#IBOutlet weak var playerPrice: UILabel!
#IBOutlet weak var priceRemaining: UILabel!
#IBOutlet weak var vsLabel: UILabel!
#IBOutlet weak var injuredLabel: UILabel!
#IBOutlet weak var gameTimeLabel: UILabel!
}
class NBADraftList: UIViewController, UITableViewDelegate, UITableViewDataSource, FIRDatabaseReferenceable{
#IBOutlet var tableView: UITableView!
let cellReuseIdentifier = "cell"
var ref: FIRDatabaseReference!
var players = [Player]()
let formatter = NumberFormatter()
override func viewDidLoad() {
let leftBarButton = UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.plain, target: self, action: #selector(myLeftSideBarButtonItemTapped(_:)))
self.title = "Select"
self.navigationItem.leftBarButtonItem = leftBarButton
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
self.tableView.rowHeight = 100.0
self.tableView.tableFooterView = UIView()
tableView.delegate = self
tableView.dataSource = self
formatter.numberStyle = .currency
formatter.maximumFractionDigits = 0
ref = FIRDatabase.database().reference().child("NBATodaysPlayers")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
var players = [Player]()
for player in snapshot.children {
players.append(Player(snapshot: player as! FIRDataSnapshot))
}
self.players = players.sorted(by: { $0.Value > $1.Value })
self.tableView.reloadData()
}) { (error) in
print("error")
}
super.viewDidLoad()
}
func myLeftSideBarButtonItemTapped(_ sender:UIBarButtonItem!)
{
self.dismiss(animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return players.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DraftListCell", for: indexPath as IndexPath) as! DraftListCell
if let formattedPrice = formatter.string(from: players[indexPath.row].Value as NSNumber) {
cell.playerPrice.text = "Game Price: \(formattedPrice)"
}
if let formattedRemainingPrice = formatter.string(from: 10000 - players[indexPath.row].Value as NSNumber) {
cell.priceRemaining.text = "Remaining: \(formattedRemainingPrice)"
}
cell.playerName.text = players[indexPath.row].Name
cell.injuredLabel.text = players[indexPath.row].Inj
cell.vsLabel.text = players[indexPath.row].visiting + " # " + players[indexPath.row].home
cell.gameTimeLabel.text = players[indexPath.row].game_time
cell.textLabel?.textColor = .white
cell.backgroundColor = .black
return UITableViewCell()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "BuyStats", sender: indexPath);
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "BuyStats" {
let buyStats = segue.destination as! BuyStats
if let indexPath = tableView.indexPathForSelectedRow {
let player = players[indexPath.row]
buyStats.selectedPlayer = player
}
}
}
}
In your cellForRowAt add following:
if cell.isSelected == true {
tableView.deselectRow(at: indexPath, animated: false)
}
Or if you want to do this specifically by Segue. You can set a global variable let's say deselectAll and check if it's true in cellForRowAt
Hope this helps