I'm making ios app. Please look my table view image below.
If you click add(+) button, you can add ENG word and its meaning in Korean(KOR) in each textfield.
After filling the textfield and click save button (it is located on right-top, "저장"), the word is added like the image below.
word is added
For example, the ENG is endless and the meaning(KOR) is "끝없는".
And, I want to use UIReferenceLibraryViewController .
If i click the cell of the list, i want to show its dictionary.
#IBAction func viewDictionary(_ sender: UITapGestureRecognizer) {
let engDictionaryWord = **engListWord**
let ViewController = UIReferenceLibraryViewController(term: engDictionaryWord)
self.present(ViewController, animated: true, completion: nil)
}
I want to use this method.
But, I don't know how to save my ENG input in engListWord.
In pic2 's swift file(addWordViewController.swift), there is prepare() method like this.
// This method lets you configure a view controller before it's presented.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
// Configure the destination view controller only when the save button is pressed.
guard let button = sender as? UIBarButtonItem, button === saveButton else {
os_log("The save button was not pressed, cancelling", log: OSLog.default, type: .debug)
return
}
let eng = engTextField.text ?? ""
let kor = korTextField.text ?? ""
// Set the meal to be passed to WordTableViewController after the unwind segue.
word = Word(eng:eng, kor:kor)
}
and viewDidLoad() method in addWordViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
engTextField.delegate = self
korTextField.delegate = self
// Set up views if editing an existing Word.
if let word = word{
engTextField.text = word.eng
korTextField.text = word.kor
}
// Do any additional setup after loading the view.
}
I don't know which variable i have to use.
There is other swift file in my project, If i misuploaded that codes above, please tell me! I will edit my question immediately.
Main.Storyboard
If i use GestureRecognizer, i made this code but I don't know it is right...
#IBAction func MyDictionary(_ sender: UITapGestureRecognizer) {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "viewDictionary", sender: indexPath)
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// I just made this identifier up, but create one yourself in the storyboard
if segue.identifier == "viewDictionary" {
// Define your vc
let libController = segue.destination as! UIReferenceLibraryViewController
// Define indexPath
let indexPath = sender as! IndexPath
// Set value in destination vc
libController.engWord = words[indexPath.row].eng
}
}
}
I think the way to go is to use the UITableViewDelegate method didSelectRowAtindexPath in the WordTableViewController (if that's the class with your table view).
A gestureRecognizer does not seem like something you want in your tableViewController as it has nice build in delegate methods to register user presses. Therefore, replace your viewDictionary(_:) function with the following:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "viewDictionary", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// I just made this identifier up, but create one yourself in the storyboard
if segue.identifier == "viewDictionary" {
// Define your vc
let libController = segue.destination as! UIReferenceLibraryViewController
// Define indexPath
let indexPath = sender as! IndexPath
// Set value in destination vc
libController.engWord = yourArrayOfEngWords[indexPath.row]
}
}
This will get your eng word of the cell you have pressed and save it to an attribute "engWord" that you then define in your UIReferenceLibraryViewController:
class UIReferenceLibraryViewController(){
var engWord: String = ""
// Rest your class properties and functions here...
}
Once it is set you can use it as you like after the segue has been performed :=)
Related
I'm trying to write a tablet tracking app for my mother but I'm having an issue I'm using an edit button to access a static table view but it is refusing to pass on the medicine object.
I need to be able to get the indexPath in prepare(for:sender:) and I'd usually use tableView.indexPathForSelectedRow and then use the row to pull the right one from the array but as I'm using a button that's not possible.
I've tried using the tag to store the row, I've tried a protocol as suggested in other answers here but I've had no success. The app still crashes when I'm trying to go to the edit screen. I have my current code below, gone through too many iterations to list them all
#IBAction func editButtonTapped(_sender: UIButton) {
let point = sender.convert(CGPoint.zero to self.tableView)
buttonIndexPath = self.tableView.indexPathForRow(at: point)
preformSegue(withIdentifier: "showDetails", sender: sender)
}
and my prepare(for:sender:) code is as follows
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetails" {
let destination = segue.destination as! MedicineDetailTableViewController
let selectedMedicine = medicines[(buttonIndexPath?.row)!]
destination.medicine = selectedMedicine
}
}
I apologise if this is something stupid that I'm missing but I'm at wit's end.
You can setup delegate for for custom cell with function like
func buttonTapped(_ sender: UITableViewCell)
Then You can use sender to get IndexPath with indexPath(for:) on tableView and perform segue.
Then Your tableView(_:cellForRowAt:) can look like this:
tableView(_:cellForRowAt:){
//setup other stuff and dequeue cell
cell.delegate = self
return cell
}
In this case, I'm following these steps:
1) Add 'Your Edit Button' into your UITableViewCell and create IBOutlet.
class YourTableViewCell: UITableViewCell {
#IBOutlet weak var yourEditButton: UIButton!
}
2) In your cellForRowAtIndexPath method, assign button tag as index.
cell.yourEditButton.tag = indexPath.row
3) Create IBAction in your View Controller. Open storyboard and connect "your edit button" with this IBAction function.
class YourViewController: UIViewController {
let selectedMedicine: Medicine? //your global Medicine variable
#IBAction func editButtonTapped(_sender: UIButton) {
//now you can access selected row via sender.tag
selectedMedicine = medicines[sender.tag]
preformSegue(withIdentifier: "showDetails", sender: nil)
}
}
Finally:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetails" {
let destination = segue.destination as! MedicineDetailTableViewController
destination.medicine = selectedMedicine
}
}
Issue: I have a table view in complaintController which has "open" buttons in it. Whenever I press on the open button I segue to DetailComplaintViewController with the data of that row, but when I go back to ComplaintController and select a different button I am presented with the same data from previous selection.
NOTE - I have created a segue from button in cell of tableView.
This is the code I am using to segue from ComplaintController to DetailComplaintController.
var passRow = 0
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let billCell = tableView.dequeueReusableCell(withIdentifier: "complaintCell") as! ComplaintTableViewCell
billCell.openBtn.tag = indexPath.row
billCell.openBtn.addTarget(self, action: #selector(btnClicked), for: .touchUpInside)
return billCell
}
func btnClicked(sender: UIButton) {
passRow = sender.tag
print("Position......\(sender.tag)")
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let rVC = segue.destination as? DetailComplaintViewController
rVC?.issueType = self.complaintListArray[passRow].issueType
rVC?.issuedescription = self.complaintListArray[passRow].description
rVC?.issuedate = self.complaintListArray[passRow].issueDate
}
The problem is that the prepare for segue will be called before your btnClicked function and thats why you are not getting the correct data.
A quick fix for your situation would be to get the button tag inside the prepare for segue method like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let button = sender as? UIButton else {
print("Segue was not called from button")
return
}
let row = button.tag
let rVC = segue.destination as? DetailComplaintViewController
rVC?.issueType = self.complaintListArray[row].issueType
rVC?.issuedescription = self.complaintListArray[row].description
rVC?.issuedate = self.complaintListArray[row].issueDate
}
Other option is to remove the segue from the button and create it on the view controller and programatically perform that segue inside your btnClicked method which is explained in this answer
I am new to Swift and I have this interesting problem.
I am trying to send the label of a table cell when I segue to another view controller where I print it. The problem is that it is printing the label of the cell that was pressed previous to this press.
Here is the code in the main view controller that passes the label:
// When a user taps on a cell on the tableView, it asks for a tag name for that image.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Cell \(indexPath) selected")
// Get cell image.
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRow(at: indexPath!) as! ImageFeedItemTableViewCell
imagePass = currentCell.itemImageView
labelPass = currentCell.itemTitle
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Send image to GreetingViewController.
if segue.identifier == "GoToGreeting" {
var greetingvc = segue.destination as! GreetingViewController
greetingvc.passedImage = imagePass
greetingvc.passedLabel = labelPass
}
}
and here is the relevant code in the view controller that receives the passed label:
var passedImage: UIImageView? = nil
var passedLabel: UILabel? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print(passedLabel?.text)
}
Any help would be appreciated.
I believe prepare(for:sender:) gets called before tableView(_:didSelectRowAt:) when you hook up that segue in the storyboard.
What you can do is just use the sender parameter of the prepare(for:sender:) method to get the information you need at the right time. When a segue is triggered by a cell, as it seems to be in your case, then that cell will be the sender passed into the the prepare method. So, you could do something like:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Send image to GreetingViewController.
if let cell = sender as? ImageFeedItemTableViewCell, segue.identifier == "GoToGreeting" {
var greetingvc = segue.destination as! GreetingViewController
greetingvc.passedImage = cell.itemImageView
greetingvc.passedLabel = cell.itemTitle
}
}
I have two table view controllers
InvoiceList view controller
InvoiceShow view controller
I use didSelectRowAtIndexPath method as bellow to get selected table cell specific value
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let rowObject = objects[indexPath.row]
let invoicehash = rowObject["hash_key"]!
}
i need to send invoicehash value to InvoiceShow controller when click the table cell of InvoiceList
i tried to use prepareForSegue function. but it is not applicable because it will trigger before the didSelectRawAtIndexPath function. so when i implemented it, gives the previous click event variable value. not correct one.
Please help me to access invoiceHash variable value from InvoiceShow controller
You will get the selected cell in prepareForSegue method itself.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let selectedIndexPath = self.tableView.indexPathForSelectedRow()!
let rowObject = objects[selectedIndexPath.row]
let invoiceHash = rowObject["hash_key"]!
let invoiceShowViewController = segue.destinationViewController as! InvoiceShowViewController
// Set invoiceHash to `InvoiceShowViewController ` here
invoiceShowViewController.invoiceHash = invoiceHash
}
You can still use a segue if you want and/or already setup on your storyboard.
You just need to connect the two view controllers in Interface Builder directly from one to another.
So, start ctrl-dragging from the controller itself and not from the TableViewCell (take a look at the screenshot)
then use the performSegueMethod with the new segue identifier like this:
self.performSegueWithIdentifier("mySegueIdentifier", sender: self)
and finally, your prepareForSegue method:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "mySegueIdentifier" {
let selectedIndex = self.invoiceTableView.indexPathForSelectedRow
//if element exist
if selectedIndex?.row < myDataSourceArray.count {
let destination = segue.destinationViewController as! InvoiceShowViewController
let invoice = myDataSourceArray[selectedIndex!.row]
destination.invoice = invoice
}
}
}
That's it!
Hello StackOverflow,
I'm just picking up swift and trying to implement data being passed between UITableView Cell to a UIViewController which will show a detailed view of the info shown on the tableview, and whenever I test the application on my emulator first time I press a table cell it passes an empty string and then when I try pressing another cell the viewController shows the string that was supposed to be seen earlier.I pasted the code I have for my tableview didSelectRowAtIndexPath below.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
var7 = lat[indexPath.item]
var6 = long[indexPath.item]
var5 = items[indexPath.item]
var1 = detail[indexPath.item]
var2 = date[indexPath.item]
var3 = wop[indexPath.item]
var4 = ViewController()
nextView.locationPassed = var1
//self.performSegueWithIdentifier("DetailPush", sender: self)
println("value stored in var1: \(var1)")
//println("The selected indexPath is \(indexPath.item + 1)")
println("The stored id is: \(storeSend)")
}
Here is my implementation for my push segue method
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "DetailPush"
{
if let crimesView = segue.destinationViewController as? ViewController {
crimesView.locationPassed = var1
//println("The passing address is: \(var1)")
}
}
}
Any idea on why I'm getting data delayed during the segue?
Thank you
Solution Found: I edited my prepareForSegue method with the following and it fixed my issue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//Adding the indexPath variable for the selected table Row within the segue
var indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow()!
if segue.identifier == "DetailPush"
{
if let crimesView = segue.destinationViewController as? ViewController {
//Then just pass the data corresponding to the array I created identified by the index of the selected row
crimesView.locationPassed = self.arrayName[indexPath.row]
println("The passing address is: \(self.addressSend)")
}
}
}
I found the solution by watching some online videos and all I did to fix my issue was redefine my prepareForSegue function with:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//Adding the indexPath variable for the selected table Row within the segue
var indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow()!
if segue.identifier == "DetailPush"
{
if let crimesView = segue.destinationViewController as? ViewController {
//Then just pass the data corresponding to the array I created identified by the index of the selected row
crimesView.locationPassed = self.arrayName[indexPath.row]
println("The passing address is: \(self.addressSend)")
}
}
}
And it seems to work like a regular segue for me.......Thank you for all the suggestions given me
you said you are doing the prepareForSegue from async request
so try this:
if segue.identifier == "DetailPush"
{
dispatch_async(dispatch_get_main_queue()) {
if let crimesView = segue.destinationViewController as? ViewController {
crimesView.locationPassed = var1
//println("The passing address is: \(var1)")
}
}
}
try to remove the line
tableView.deselectRowAtIndexPath(indexPath, animated: false)
see if it still happens.
maybe move it to the end