swift: tableview returning animation - ios

I want to create tableview like on image(https://www.raizlabs.com/dev/wp-content/uploads/sites/10/2016/05/Default-Deselection.gif) In this table view I see animation of selected row after returning to the first controller with table view.
But when I create default tableview in my project animation of selected row after returning to the first controller not show. How to fix it?
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(format: "Cell%d", indexPath.row), for: indexPath)
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.destination is ViewController) {
(segue.destination as? ViewController)?.index = (self.tableView.indexPathForSelectedRow?.row)!
}
}
}

If you want the selected row color to fade out after navigating back(pan the screen edge), you can use this:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let indexPath = tableView.indexPathForSelectedRow {
tableView.deselectRow(at: indexPath, animated: true)
}
}

Related

Multiple selected rows to show multiple images in other view controller

Choosing a string in a UITableViewController, shows pic of the same name in another view controller, which works as it should.
But the problem is when I want to choose multiple strings to show multiple different pics.
I've been trying to add another IBOutlet, doubling stuff, but it was just showing me the same pic twice.
Any idea?
multiple selection = true
First VC segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "tablesegue" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let selectedRow = indexPath.row
let passingVal = segue.destination as! Tabulka_data
passingVal.selectedImageName = self.tableItems[selectedRow]
}
}
}
secondVC:
#IBOutlet weak var pic: UIImageView!
var selectedImageName:String = ""
override func viewWillAppear(_ animated: Bool) {
self.pic.image = UIImage(named: selectedImageName)
}
two choices
You can try this
let yourDataArray = ["name 1","name 2","name 3","name 4","name 5"]
var imageSelected = [String]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yourDataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = yourTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = yourDataArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
imageSelected.append(yourDataArray[indexPath.row])
print(imageSelected)
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
for (index, element) in imageSelected.enumerated() {
if element == yourDataArray[indexPath.row] {
imageSelected.remove(at: index)
}
}
print(imageSelected)
}
You can use didSelectRowAt and didDeoRowAt to see which rows are selected, then just pass imageSelected to the second viewController

Segue not firing from custom tableView cell

I'm experiencing what I'm sure is a beginner's mistake. I have a TableViewController that should segue to a second TableViewController upon selection of a custom cell.
I've segued to a UIViewController from a custom cell in the past but I can't figure out for the life of me why this segue isn't firing. Here's the code for the entire controller that should be firing the segue. Thanks in advance!
import UIKit
class SourcesViewController: UITableViewController {
var sources: [Source] = []
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.isNavigationBarHidden = false
self.navigationItem .setHidesBackButton(true, animated: false)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sources.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell_01", for: indexPath) as? SourceCell
else {
return tableView.dequeueReusableCell(withIdentifier: "cell_01", for: indexPath)
}
let currentSource = sources[indexPath.row]
cell.sourceLabel.text = currentSource.name
return cell
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let indexPath = tableView.indexPathForSelectedRow {
let sourceToSend = sources[indexPath.row]
if let destination = segue.destination as? ArticlesViewController {
destination.source = sourceToSend
}
}
}
}
Your segue doesn't get called because you are not invoking it. UIViewController has perfromSegue method that you should use for that purpose.
From what I see you would want to perform the segue after tapping the cell. To achieve this add UITableViewDelegate method and perform segue from there:
/// - SeeAlso: UITableViewDelegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "your_identifier_from_the_storyboard", sender: nil)
}

Getting correct index row from sectioned tableview after JSON download Swift 4

JSON data is already alphabetized before being downloaded. The app correctly divides the data into sections, creates the section title based off of the first letter, and lists all names starting with that letter in the correct section. The problem is each section repeats the same data once it transitions to the detail view controller. Sections B, C, etc. show all of correct names but repeat the "A" names when going to the detail view controller. How can I get the selected cell and the details view controller to match again?
func numberOfSections(in tableView: UITableView) -> Int {
return figuresByLetter.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return figuresByLetter[section].key
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return figuresByLetter[section].value.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "figureCell", for: indexPath)
cell.textLabel?.text = figuresByLetter[indexPath.section].value[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetails", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? FigureViewController {
destination.figure = figures[(tableView.indexPathForSelectedRow?.row)!]
}
}
Let me know if there is any other code needed to answer the question!
struct FigureStats: Decodable {
let name: String
let number: String
let weapon: String?
let desc: String?
let year: String?
}
In the detail view controller:
class FigureViewController: UIViewController {
var figure:FigureStats?
override func viewDidLoad() {
super.viewDidLoad()
nameLabel.text = figure?.name
numberLabel.text = figure?.number
weaponLabel.text = figure?.weapon
descLabel.text = figure?.desc
yearLabel.text = figure?.year
}
}
Try using this property. I hope it helps you.
class YourClass: UIViewController {
var currentFigure: FigureStats!
func numberOfSections(in tableView: UITableView) -> Int {
return figuresByLetter.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return figuresByLetter[section].key
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return figuresByLetter[section].value.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "figureCell", for: indexPath)
cell.textLabel?.text = figuresByLetter[indexPath.section].value[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
currentFigure = figuresByLetter[indexPath.section].value[indexPath.row]
print(currentFigure)
performSegue(withIdentifier: "showDetails", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? FigureViewController {
print(currentFigure)
destination.figure = currentFigure
}
}
class FigureViewController: UIViewController {
var figure:FigureStats?
override func viewDidLoad() {
super.viewDidLoad()
print(figure)
nameLabel.text = figure?.name
numberLabel.text = figure?.number
weaponLabel.text = figure?.weapon
descLabel.text = figure?.desc
yearLabel.text = figure?.year
}
}
I think your problem is that you don't send data to your showDetails (I don't see how you do it) so you see data which did add to storyboard but not data from your model, check it.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showDetails", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetails" {
let controller = (segue.destination as! UINavigationController).topViewController as! YourViewController
let row = (sender as! IndexPath).row
controller.figuresByLetter = figuresByLetter[row]
}
}

How to save reorder of rows in TableView with Swift

I search already a few days to the answer on the question how can I save the reorder TableView with Swift? So many tutorials on the internet show how to reorder but not how to save with UserDefaults.
This is my code right now. What do I wrong?
Please can you help me to the solution? Thank you very much.
import UIKit
class soundboardTableViewController: UITableViewController {
var list = ["January","February","March","April","May","June", "July","August","September","October","November", "December"]
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = self.editButtonItem
let blockItems = UserDefaults.standard.object(forKey:"soundboard")
if(blockItems != nil) {
list = blockItems as! [String]
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return list.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = list[indexPath.row]
return cell
}
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
/* Override to support editing the table view.*/
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
list.remove(at: indexPath.row)
UserDefaults.standard.set(self.list, forKey:"soundboard")
UserDefaults.standard.synchronize()
tableView.reloadData()
}
}
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt indexPath: IndexPath, to: IndexPath) {
let itemToMove = list[indexPath.row]
list.remove(at: indexPath.row)
list.insert(itemToMove, at: indexPath.row)
UserDefaults.standard.set(self.list, forKey:"soundboard")
UserDefaults.standard.synchronize()
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
if(self.isEditing) {
}
}
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
}
Your code in tableView(_:moveRowAt:to:) has some errors. You should change it to:
override func tableView(_ tableView: UITableView, moveRowAt indexPath: IndexPath, to: IndexPath) {
let itemToMove = list[indexPath.row]
list.remove(at: indexPath.row)
list.insert(itemToMove, at: to.row)
UserDefaults.standard.set(self.list, forKey:"soundboard")
}
Notice that I removed UserDefaults.standard.synchronize(). You should remove it from your other methods as well, since it is kind of a non-sense in this case. I have also changed list.insert(itemToMove, at: indexPath.row) to list.insert(itemToMove, at: to.row), because you need to place it to the "destination" index, and not put it back from where you removed it.
The rest of your code seems fine. It should be working once you perform these changes.

Recognize which tableviewcell is selected and pass value to another viewcontroller [duplicate]

This question already has answers here:
Send data from TableView to DetailView Swift
(4 answers)
Closed 5 years ago.
I'm trying to recognize which tableviewcell is selected and after that i want to get the label value of that cell and pass it to the next view controller. My cell has a Label value which is string and a Number value which is Int. I'm using a firebase database to get all that data.
My code:
import UIKit
class PlacesTableViewController: UITableViewController {
//MARK: Properties
#IBOutlet weak var placesTableView: UITableView!
var places = [Places]()
override func viewDidLoad()
{
super.viewDidLoad()
// Loads data to cell.
loadData()
}
override func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
//return the number of rows
return places.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "PlacesTableViewCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? PlacesTableViewCell else {
fatalError("The dequeued cell is not an instance of PlacesTableView Cell.")
}
let place = places[indexPath.row]
cell.placeLabel.text = place.name
cell.ratingControl.rating = place.rating
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
print(places[indexPath.section])
self.performSegue(withIdentifier: "ShowCommentsTableViewController", sender: nil)
}
}
you can follow this thread to be useful send-data-from-tableview-to-detailview-swift
You have to create variable in destination view controller and store data in those Variable before Moving to Destination View controller.
This link will help you for this.
Try this:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let selectedPlace = places[indexPath.section]
self.performSegue(withIdentifier: "ShowCommentsTableViewController", sender: selectedPlace)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let selectedPlace = sender as? Places,
let destViewController = segue.destination as? SecondViewController {
destViewController.place = selectedPlace
}
}

Resources