Passing value selected cell to another ViewController - arrays

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
}
}

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

swift auto refresh Cell

which I add or remove from another ViewController
Im display this array.count in tableView
How in swift I can auto updates cell for array.count?
without Timer and Pull to refresh
Or how can I make refresh when loadedCart.count haw change?
Thanks
class TestTABLEVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableViewT: UITableView!
var CellT = TestTableViewCell()
var def = UserDefaults.standard
var loadedCart = [[String:Any]]()
override func viewDidLoad() {
super.viewDidLoad()
tableViewT.estimatedRowHeight = 100
tableViewT.dataSource = self
tableViewT.delegate = self
loadedCart = UserDefaults.standard.array(forKey: "cartt") as? [[String: Any]] ?? []
//Here need add auto update
}
cell for row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TestTableViewCell
let item = loadedCart[indexPath.row]
cell.nameLbl?.text = item["name"] as? String
cell.priceLbl.text = item["price"] as? String
cell.qntLbl.text = item["qty"] as? String
let im = item["image"] as? NSData
cell.PhoroUmage.image = UIImage(data: im! as Data)
return cell
}
Btn, when click - remove arr and reload cells
#IBAction func Btn(_ sender: UIButton) {
def.removeObject(forKey: "cartt")
print("remove is OK")
//Here need add auto update when btn pressed
}
If I understand you correctly, you can use reactive programming for this. For example Bond framework can be used like this:
let todoItems: SafeSignal<[TodoItem]> = ....
let tableView: UITableView = ...
class TodoItemCell: UITableView Cell { ... }
...
todoItems.bind(to: tableView, cellType: TodoItemCell.self) { (cell, item) in
cell.titleLabel.text = item.name
}
Using this framework, your table view will automatically reload when there are any changes to the source array. You will find more about usage on table views at this link.
you probably need to use notifications. i.e. send a notification when something new gets added to your cart.
Then set up an observer and, every time the observer notices a change, update the tableview with reload data.
A similar use case is listed here I think but would need to be adapted for your needs (if you need more help someone more expert than me will be able to help probably with the specifics!) Automatically Reload TableViewController On Rewind
Add
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let carts = UserDefaults.standard.array(forKey: "cartt") as? [[String: Any]] {
loadedCart = carts
}
DispatchQueue.main.async{
self.tableViewT.reloadData()
}
}

How to add json data to array or similar using Swift

I am fairly new to Swift and I am having a few issues with getting understanding how to do what I want to do.
I am currently testing some stuff with json.
What I am trying to do is to append the data I get from my json data into an array. And when my array contains the data I wish to present it to my UICollectionView. I am assuming that I should be using an array.
import UIKit
import Foundation
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func getData() {
let path = "http://myurl/test.json"
let url = URL(string: path)
let session = URLSession.shared
let task = session.dataTask(with: url!) { (data: Data?, response: URLResponse?, error: Error?) in
let json = JSON(data: data!)
for result in json["dokumentstatus"]["dokutskott"]["utskott"].array! {
let punkter = result["punkt"].string!
print("punkt: \(punkt)")
let rubrik = result["rubrik"].string
print("rubrik: \(rubrik)")
let forslag = result["forslag"].string
print("förslag: \(forslag)")
}
}
task.resume()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return //someArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCollectionViewCell
cell.customLabel.text = //Put the data form rubrik variable
cell.customTW.text = //Put the data from foreleg variable
return cell
}
}
the function getData() gets the correct json data I just need help understanding how to put this data to an array.
(Also, I know I probably shouldn't be getting the data in the ViewController, but this is only a test.)
import Foundation
class Information: NSObject {
var punkter: String?
var rubrik: String?
var forslag: String?
}
I'm thinking that maybe I should be using an array that looks something like this:var someArray = [Information]()
But I do not know how to then use my getData()
Or maybe I should be using three different arrays, one for each of my json variables.
Since you're still using a custom class (well done!, three different arrays are horrible) it's correct to declare a data source array like you suggested
var someArray = [Information]()
Most likely a struct is sufficient, I recommend to use non-optional strings
struct Information {
var punkter : String
var rubrik : String
var forslag : String
}
If the properties won't change you could even use let to make the properties constants.
To populate the array use the nil coalescing operator to check for nil,create the Information instance with the memberwise initializer and append the instance to the datasource array. Then reload the collection view on the main thread.
...
for result in json["dokumentstatus"]["dokutskott"]["utskott"].array! {
let punkter = result["punkt"].string ?? ""
let rubrik = result["rubrik"].string ?? ""
let forslag = result["forslag"].string ?? ""
let information = Information(punkter:punkter, rubrik:rubrik, forslag:forslag)
self.someArray.append(information)
}
DispatchQueue.main.async {
self.collectionView.reloadData()
}
...
Edit:
To display the data in cellForItemAtIndexPath use
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomCollectionViewCell
let information = someArray[indexPath.row]
cell.customLabel.text = information.rubrik
cell.customTW.text = information.foreleg
return cell
}

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
}
}

Resources