Removing items from array in custom tableViewCell - arrays

I have a custom tableviewHeaderFooterView where I set up a target event for the button in the custom tableViewCell class (checkButton is the button and its background image changes to a checkmark when a user clicks on it).
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let userModel = Data.userModels[section]
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId") as! SectionHeader
cell.setup(model: userModel)
cell.checkButton.tag = section
cell.checkButton.addTarget(self, action: #selector(handleTap), for: .touchUpInside)
return cell.contentView
}
And in that function I want to create or remove items from an array depending on whether the user taps on a cell or not (i.e. if they tap on the button, then add something to the array, but if they tap on that button again, then remove that object from the array.)
#objc func handleTap(sender: UIButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected == true {
let model = ItemModel(itemName: item, price: price)
ItemModelFunctions.createItem(for: sender.tag, using: model)
}
if sender.isSelected == false {
ItemModelFunctions.removeFromUser(from: sender.tag)
}
print(sender.tag)
}
Here are the createItem and removeFromUser functions:
struct ItemModelFunctions {
static func createItem(for userIndex: Int, using itemModel: ItemModel) {
Data.userModels[userIndex].itemModels.append(itemModel)
}
static func removeFromUser(from userIndex: Int) {
Data.itemModels.remove(at: userIndex)
}
}
When I tap on the button twice to remove it from the array, I get an error saying Data.itemModels.remove(at: userIndex) is out of range.
I know using a prototype cell for a tableViewHeaderFooterView isn't exactly the correct way, but I've seen other programmers and YouTubers do this with success. Are my issues coming from using a prototype cell? Or am I removing the item from the array in the wrong way? Thank you all for your help!

// Please maintain one more array i.e selectedIndexArray and follow below code.
var selectedIndexArray = [Integer]()
#IBAction func buttonTapped(_ sender: UIButton) {
let button = sender
if selectedIndexArray.contains(button.tag) {
button.tag --> Remove this tag from selectedIndexArray
let model = ItemModel(itemName: item, price: price)
ItemModelFunctions.createItem(for: sender.tag, using: model)
} else
{
selectedIndexArray.append(button.tag)
ItemModelFunctions.removeFromUser(from: sender.tag)
}
//reload tableview.
self.tableView.reloadData()
}

The checkButton.addTarget function will run each time your section header is reused.
Then it will duplicate event for cell when reuse many times.
I think you should not use this solution. Instead of that, I think you should write delegate way to solve your problem.
Ex:
protocol SectionHeaderDelegate: class {
func checkButtonDidTap(section: SectionHeader)
}
class SectionHeader: UITableViewCell {
weak var delegate: SectionHeaderDelegate
#IBOutlet weak var checkButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
checkButton.addTarget(self, action: #selector(handleTap), for: .touchUpInside)
}
func handleTap() {
self.delegate.checkButtonDidTap(section: self)
}
}
and you set cell.delegate = self in viewForHeaderInSection function. And implement protocol SectionHeaderDelegate.

Thanh Vu's solution works. Another solution would be to add an IBAction to your ViewController:
#IBAction func buttonTapped(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
let cell = sender.superview?.superview as! SectionHeader
if let indexPath = mainTableView.indexPath(for: cell) {
// if sender.isSelected etc...
}
}

Related

How do I get the index of an array to properly save a unique value to Firebase?

In each row of a tableview there is a label and button. The label displays a quotes from an array. Users can tap the button to save the quote. Right now it works fine with UserDefaults, but I want to also save the information to Firebase. I can't seem to figure out how to get the quote to save to Firebase based on the heart/row that was tapped. I thought I could use IdexPath, but I can't seem to get it right. I'd like to save each quote as a unique value in Firebase and be able to delete it when the button is tapped again. However, I'm not so familiar with firebase.
I thought I could use IdexPath to determine which row was selected and then grab the label in that row to send to Firebase, but I can't seem to get it right. Instead I got an error preventing the code from running "Instance member 'row' cannot be used on type 'IndexPath'; did you mean to use a value of this type instead?"
import UIKit
import FirebaseDatabase
import FirebaseAuth
class QuotesMainViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var quotesTableView: UITableView!
struct Quote: Codable {
var label: String
var like: Bool = false // a priori, false
}
var quoteList: [Quote] = []
override func viewDidLoad() {
super.viewDidLoad()
quotesTableView.delegate = self
quotesTableView.dataSource = self
let defaults = UserDefaults.standard
if let data = defaults.data(forKey: "QuoteListKey") {
if let array = try? PropertyListDecoder().decode([Quote].self, from: data) {
quoteList = array
}
} else {
quoteList = [Quote(label: "Quote1"), Quote(label: "Quote2"), Quote(label: "Quote3")]
}
}
#IBAction func likeTapped(_ sender: UIButton) {
var ref: DatabaseReference?
ref = Database.database().reference()
quoteList[sender.tag].like.toggle() // update the dataSource ; sender.tag gives the row in the array
if quoteList[sender.tag].like {
sender.setImage(UIImage(named: "GreenHeart"), for: .normal) // You can change here or ask for a reloadData()
guard let user = Auth.auth().currentUser?.uid else { return }
ref!.child("users").child(Auth.auth().currentUser!.uid).child("Quotes").setValue(quoteList[IndexPath.row].label)
if let data = try? PropertyListEncoder().encode(quoteList) {
UserDefaults.standard.set(data, forKey: "QuoteListKey")
}
} else {
sender.setImage(UIImage(named: "blankHeart"), for: .normal)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return quoteList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = quotesTableView.dequeueReusableCell(withIdentifier: "cell") as! QuotesTableViewCell
cell.quoteLabel.text = quoteList[indexPath.row].label
cell.likeButton.tag = indexPath.row // Use tag to reference the cell, not to set true / false
cell.likeButton.setImage(UIImage(named: quoteList[indexPath.row].like ? "GreenHeart" : "blankHeart"), for: .normal)
return cell
}
}

Item appends to array in one view controller but not in another

I have a TableView that displays a list of entries in the cells. The entries are stored in an array. The user enters in text for the entries in another view controller (modal), hits "Save", and after .reloadData(), the new entry should append to the array and display in the TableView. The array lives in the HomeController.
To pinpoint where the problem might be, I've tried appending some text in the HomeController, then appending to the same array from the NotesController. In the latter, when I print homeController.entryInput, I'm expecting ["hello", "goodbye"]. Instead, I only get ["goodbye"].
Also, when I click on "Save" in NotesController a second time, I get ["goodbye"] again instead of ["goodbye", "goodbye"]. So it looks like the array gets overrided.
I've also tried hard coding items into the array, and they show up fine in the TableView. When I append an item from NotesController, it appends to the array but doesn't show on the TableView, and when I add another item from the same ViewController, it overwrites the first item I appended rather than adding it as a new item.
HomeController:
class HomeController: UIViewController {
let tableView = UITableView()
var entryInput: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
}
func setupTableView() {
tableView.delegate = self
tableView.dataSource = self
self.entryInput.append("hello")
print(entryInput)
tableView.register(HomeCell.self, forCellReuseIdentifier: reuseIdentifier)
let height = view.frame.height
tableView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: height)
tableView.backgroundColor = .white
view.addSubview(tableView)
}
extension HomeController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return entryInput.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! HomeCell
cell.entryTextLabel.text = entryInput[indexPath.row]
return cell
}
NotesController:
class NotesController: UIViewController {
let homeController = HomeController()
...
let saveBtn = UIView().navigationBtn(text: "Save")
let homeController = HomeController()override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
saveBtn.addTarget(self, action: #selector(save(sender:)), for: .touchUpInside)
}
#objc func save(sender: UIButton) {
homeController.entryInput.append("goodbye")
homeController.tableView.reloadData()
print(homeController.entryInput)
dismiss(animated: true, completion: nil)
}
}
I've looked all around Stack Overflow and other websites about appending to arrays but for some reason can't seem to figure out why I can't append to an array in another class.
Because you have create new HomeController in NotesController that doesn't reference to your current HomeController.
class NotesController: UIViewController {
let homeController = HomeController()
}
When HomeController want to open NotesController.
And NotesController want to communicate back to HomeController.
You should pass HomeController reference to NotesController.
func routeToNotesController() {
let vc = NotesViewController()
vc.homeController = self
let nc = UINavigationController(rootViewController: vc)
present(nc, animated: true)
}
Answer your questions.
From the NotesController after save called. You're expecting
["hello","goodbye"] but you get ["goodbye"] instead.
Because you are instantiate HomeController in
NotesViewController The homeController that you create is not
the same HomeController appear on the screen, It's new so
homeController and entryInput still empty because viewDidLoad isn't
call.
When you add another item from NotesViewController, You're
expecting ["goodbye", "goodbye"] but you get ["goodbye"] instead.
According the first answer. You create new homeController(that not
relate to existing one on the screen) inside NotesController
every time it appear on the screen.
Here is the result.
Left image show HomeController.
Middle image show HomeController that open InputsController.
Right image show HomeController that updated by InputsController.
My implementation.
class ListViewController: UITableViewController {
var entryInput: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "ListViewController"
tableView.backgroundColor = .white
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(add))
entryInput.append("hello")
tableView.reloadData()
}
#objc func add() {
let vc = InputViewController()
vc.listViewController = self
let nc = UINavigationController(rootViewController: vc)
present(nc, animated: true)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return entryInput.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = entryInput[indexPath.row]
return cell
}
}
class InputViewController: UIViewController {
weak var listViewController: ListViewController?
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "InputViewController"
view.backgroundColor = .white
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(save))
}
#objc func save() {
listViewController?.entryInput.append("goodbye")
listViewController?.tableView.reloadData()
dismiss(animated: true)
}
}
It looks like the line:
let homeController = HomeController()
creates a new instance of the class HomeController and does not refer to the already existing ViewController. Which means: modifying the array in the new instance of HomeController won't affect your main ViewController.
This also leads to the answer of your question about the missing "hello"-element in your array. When you create the object homeController it's array does not have any elements.
When #objc func save(sender: UIButton) get's called, you append "goodbye" to the empty array.
By calling dismiss(...) you are returning to the original version of your HomeController() which does not know anything about the other instance you created in NotesController().
To achieve what you are trying to do, I recommend reading more about how to pass data between ViewControllers:
How do you share data between view controllers and other objects in Swift?
https://www.hackingwithswift.com/example-code/system/how-to-pass-data-between-two-view-controllers

How to update value of an item in Class based on UISwitch action?

I have item class as shown below:
struct Cur: Decodable {
let id: String?
let name: String?
let symbol: String?
let rank: String?
let switchVal: Bool?
}
This class fills an array and array fills UITableView.
Here how I access UISwitch action:
#IBAction func switchBtn(_ sender: UISwitch) {
if sender.isOn {
// See if user is in Search Mode
if inSearchMode {
// if user in search mode get the Cur from filtered array
if let switchRank = filterCur.index(where: {$0.switchVal}) {
print("This is the rank: \(filterCur[switchRank].rank!)")
}
} else {
if let switchRank = Cur.index(where: {$0.switchVal}) {
print("This is where it is: \(Cur[switchRank])")
}
}
} else {
// Handle deleting previously selected Curs
}
}
In order for me to find which item in the array is Switched On/Off I have to have the array already updated (items switchVal = true?). But, to update the array I need to know which item's switch is triggered.
So, where is my mistake?
Thank you
One way to solve this problem is to give every UISwitch the index of Cur by assigning it to the tag attribute.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.switch.tag = indexPath.row
...
}
Since you now know that every switch has the index, you can get the item by accessing your array with the switch's tag.
#IBAction func switchBtn(_ sender: UISwitch) {
let index = sender.tag
let cur = Cur[index]
}

Save text in array and display in a table view

I am trying to create an app that displays a table view based on an array of strings.
I have one view controller and a smaller content view within it. In the view controller there is a text field and a button that should save the written text in an array and display it in the table view controller. As well as embedding it in the content view.
I don't know how to save the written text and to add it in the array, perhaps using append.
How can I display the array in the table view and to save the array in NSUserDefaults?
EDIT:
Here's an image of the view controller and the content view. I want to insert one string in the text field (the one over the green button Save), then I tap the green button and the string I wrote is added in the array and displayed in a table view cell of the table view controller embed in the content view. At the same time, the text field return empty, but I already know how to clear it. Then, I can re-write texts in the text field and it should repeats the actions I just described.
A the moment isn't so important to save in NSUserDefaults.
Thanks for the help. :)
http://i.stack.imgur.com/z5uTc.png
EDIT 2:
MainVC
import UIKit
class mainVC: UIViewController {
#IBOutlet var txtField: UITextField!
var embTableVC: tableVC!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "embededTableVC" {
embTableVC = segue.destinationViewController as! tableVC
}
}
#IBAction func Save() {
if let Text = txtField.text {
if txtField.text == "" {
myArray.append(Text)
let row = myArray.count-1
let indexPath = NSIndexPath(forRow: row, inSection: 0)
embTableVC.myTableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
txtField.text = ""
txtField.resignFirstResponder()
}
}
TableVC
import UIKit
var myArray = [String]()
class tableVC: UITableViewController {
#IBOutlet var myTableView: UITableView! {
didSet {
myTableView.dataSource = self
myTableView.delegate = self
}
}
override func viewDidLoad() {
super.viewDidLoad()
myTableView.dataSource = self
myTableView.delegate = self
myTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "customcell")
// Do any additional setup after loading the view, typically from a nib.
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
myTableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCellWithIdentifier("customcell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = myArray[indexPath.item]
return cell
}
Thanks a lot :)
To store the information:
// Get the standardUserDefaults object, store your UITableView data array against a key, synchronize the defaults
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:arrayOfImage forKey:#"tableViewDataImage"];
[userDefaults setObject:arrayOfText forKey:#"tableViewDataText"];
[userDefaults synchronize];
To retrieve the information:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSArray *arrayOfImages = [userDefaults objectForKey:#"tableViewDataImage"];
NSArray *arrayOfText = [userDefaults objectForKey:#"tableViewDataText"];
// Use 'yourArray' to repopulate your UITableView
On first load, check whether the result that comes back from NSUserDefaults is nil, if it is, you need to create your data, otherwise load the data from NSUserDefaults and your UITableView will maintain state.
In Swift, the following approach can be used:
let userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(arrayOfImage, forKey:"tableViewDataImage")
userDefaults.setObject(setObject:arrayOfText, forKey:"tableViewDataText")
userDefaults.synchronize()
var arrayOfImages = userDefaults.objectForKey("tableViewDataImage")
var arrayOfText = userDefaults.objectForKey("tableViewDataText")
Hope this helps. You can also use a xcdatamodeld to save and retrieve data.
Here's a simple solution for storing the text in an array, a better option than NSUserDefaults if you might have a large number of Strings.
First, you will need to have an Array of Strings in the View Controller managing the Table View. Then, you will need a way to access that Array and edit it.
I would store a reference to the table view controller within the first view controller (with the container). To first set this reference, use the embed segue.
In your storyboard, the arrow connecting the first VC to the table VC is actually an embed segue that fires upon load of the container view. Click the segue, and in the attributes inspector in Xcode change the identifier to some String such as "embedTableVC".
Then we can set the reference in the first view controller. Here's some relevant code, assuming the view controller with the container has a class of MainViewController and the table view controller within the container has a class of TableViewController:
class MainViewController: UIViewController {
var embededTableVC: TableViewController!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "embedTableVC" {
embededTableVC = segue.destinationViewController as! TableViewController
}
}
}
Once the main view controller loads, the container will be loaded, which will then cause the segue to run, which will cause prepareForSegue to be called. In this implementation, we are storing the table view controller in a property on our main view controller so we can access it. Since classes are reference types, this property will refer to the same object, not a copy.
Then, you get the text from the text field once the save button is pressed, and set it to the array in the table VC, like this:
#IBAction func save() {
if let text = textField.text {
if text != "" {
embededTableVC.valueArray.append(text)
// and if you want to go ahead and add it to the array from here instead of using delegation or notification observance
let row = embededTableVC.valueArray.count - 1
let indexPath = NSIndexPath(forRow: row, inSection: 0)
tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
}
The if-let syntax ensures the text property of the text field is not nil.
I believe this is what you were looking for, but keep in mind that everything will be gone upon app relaunch, since we're not using NSUserDefaults or Core Data to store anything to the device's drive. You'll want a combination of the two approaches if you need persistence.
Edit:
As far as populating the table view with content from the array, you should consult Apple's Docs, as explaining it here would get pretty lengthy and the information may be found easily. Alternatively, you can check out this article to get an understanding for populating the table view, or see this question. You will need to implement numberOfSectionsInTableView, numberOfRowsInSection, and cellForRowAtIndexPath at a minimum for your table view.
Edit 2:
After reading your code, I'd say there are many things that probably ought to be changed eventually, but just to get it to work for now, the following changes need made for now:
Change this (from Save())…
if let Text = txtField.text {
if txtField.text == "" {
myArray.append(Text)
let row = myArray.count-1
let indexPath = NSIndexPath(forRow: row, inSection: 0)
embTableVC.myTableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
…to this
if let text = txtField?.text {
if text != "" { // Notice the two changes on this line
myArray.append(text)
let row = myArray.count - 1
let indexPath = NSIndexPath(forRow: row, inSection: 0)
embTableVC.myTableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
Change this (in cellForRowAtIndexPath)…
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCellWithIdentifier("customcell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = myArray[indexPath.item]
return cell
}
…to this
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCellWithIdentifier("customcell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = myArray[indexPath.row] // Notice `row`, not item`
return cell
}
If you're still getting a crash because a nil optional was unwrapped, which is highly possible, I need to know what line Xcode crashes on and I need to know what the error says.
import UIKit
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
**var message = ["a","b"]
var toPass: String!**
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view.
**message.append(toPass)**
}
#IBAction func SendButon(_ sender: UIButton) {
performSegue(withIdentifier: "segue2", sender: nil)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// tableView.reloadData()
return message.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.register(UINib(nibName: "TableViewCell", bundle: nil),
forCellReuseIdentifier: "CellFor")
let cell = tableView.dequeueReusableCell(withIdentifier: "CellFor", for: indexPath) as! TableViewCell
cell.labelView.text = message[indexPath.row]
return cell
}
}

Passing value selected cell to another ViewController

I have two ViewControllers. For the first ViewController, it displays my Array data on the table. I want to get the indexPath of the selected cell, and pass this data to another ViewController.
In my First ViewController
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
var nameList = [NameManager]()
#IBOutlet weak var NameTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
NameTable.dataSource = self
GetData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func GetData(){
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.json-generator.com/api/json/get/bPfifKWNaq?indent=2")!)
request.HTTPMethod = "GET"
let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if let error = error {
print(error)
}
if let data = data{
do{
let resultJSON = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions())
let resultArray = resultJSON as? NSArray
for jsonObjectString in resultArray!{
let code = jsonObjectString["code"] as! String
let name = jsonObjectString["name"] as! String
let description = jsonObjectString["description"] as! String
self.nameList.append(NameManager(code: code, name: name, description: description))
}
self.nameList.count
dispatch_async(dispatch_get_main_queue(), {
self.NameTable.reloadData()
})
}catch _{
print("Received not-well-formatted JSON")
}
}
if let response = response {
let httpResponse = response as! NSHTTPURLResponse
print("response code = \(httpResponse.statusCode)")
}
})
task.resume()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
let count = nameList.count
return count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let myCell = NameTable.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as UITableViewCell
myCell.textLabel?.text = nameList[indexPath.row].name
myCell.detailTextLabel?.text = nameList[indexPath.row].description
return myCell
}
In my Second ViewController, which is also another class, I want to capture the indexPath of what was selected. Using the index value, I search my Array and pass that particular object to the next class. I don't have codes for this as I don't know how it works.
You could create a property outside the scope of your class and then set that within the cellForRowAtIndexPath method. That property could be accessed in your second view controller. You’ll want to look at the tableview method didSelectRowAtIndexPath as that will be where you set your property to the cell that’s been selected.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
appDelegate().index = indexPath.row
}
I’ve made a super simple project on github showing two ways of creating a property outside the scope of your view controller. One way is creating a variable within AppDelegate to be accessed via a singleton, the other is a Globals.swift file.
Hope this helps!
If you want to pass values to the controller which pops after tapping on the cell, using a singleton wouldn't be an elegant way. If you are using storyboards, then you have to use 'prepare for segue'. You implement the method in the class that handles the transfer and set all the properties in another view controller.
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "SecondVC") {
// set properties
}
}

Resources