I am using coreData and simply sending data from the tableView cell content that is text and the color of the cell to a modal view controller. In modalVC, I am able to change the text and when I press done, the tableView gets updated.
Now I want to add a feature in which if the text is removed completely and the user press done, the data from coreData should be deleted and so should the tableView row.
Here is what I am doing in order to achieve this:
#IBAction func doneButton(_ sender: Any) {
if edittasktextview.text.isEmpty == true
{
moContext.delete(editnotes[num] as NSManagedObject)
editnotes.remove(at: num)
}
else
{
editnotes[num].sNote = edittasktextview.text
}
}
num is the indexPath which I am sending from the first VC to modal VC (kind of keeping track of which cell is tapped)
Now when I dismiss the modal viewcontroller, a notification is send to the firstVC to trigger a func which essentially reloads the tableView in firstVC. However, while the row is no longer seen in the tableview, I still have have to go back to my rootVC and then back to first VC to update the tableView completely.
Help will be appreciated!
Use an NSFetchedResultsController to let your table view be triggered by CoreData changes.
Here's a tutorial to get you started. There are various other good tutorials and YT videos that are easy to find.
Related
I have two tabs. The first tab contains a UITableViewController, with its tableView's cells containing some words. The second tab is for settings, containing a tableView, with a cell for setting font size. After the user taps the cell, the user will enter the interface for changing the font size. When the user presses the "save" button, (a button in the editing-font-size interface to save the adjusted font size.) the top view controller is popped back to the original tableView for settings.
I use observers to post notification when the save button is pressed, and the respective observers will update its view. I added an observer in the tableView for settings, and it works. When the top view controller for editing font size is popped, the original tableView is presented with adjusted font size.
However, when I added an observer in the UITableViewController in the first tab, the tableView is not reloaded. I have added a print message in the selector method of NotificationCenter.default.addObserver(_:selector:name:object:) and confirm that the selector method is called. The selector method looks like this:
#objc func reloadTableView() {
print("The method is called.")
tableView.reloadData()
}
The code that I use the font size in the first tab's tableView cell:
labelOne.font = UIFont(descriptor: fontDescriptor, size: fontSizeForLabelOne)
labelTwo.font = UIFont(descriptor: fontDescriptor, size: fontSizeForLabelTwo)
It seems very confusing to me, since the method to reload tableView is called, yet the table view is not reloaded? And since the font size is changed, when I scroll the tableView the new cells are randomly in the old font size or adjusted font size.
I have also tried it with labels, and it works on them even if it is in a different tab. In other words, I think the problem only occurs for tableView.
On the other hand, since it works for the table view in setting tab, am I right to say that tableView can only be reloaded when tableView.reloadData() is called when the tableView is about to be presented? If tableView is not presented and tableView.reloadData() is called, nothing will happen, and everything remains the same?
In short, is there anyway to ensure that tableView is reloaded when I change my font size?
Eventually I found a solution by, since my view controllers are managed by navigation controller, I pop the view controller and load it again as the alternative to reload the table view. Namely,
#objc func reloadTableView() {
navigationController.popViewController(animated: false)
navigationController.pushViewController(theViewController, animated: false)
}
The only downside of this is that the view controller will be reset to its initial state, i.e. if the table view in the view controller is scrolled down, when the user goes back to the view controller from setting, the table view is reset to its top position and does not show where it was scrolled to.
#objc func reloadTableView() {
print("The method is called.")
DispatchQueue.main.async {
tableView.reloadData()
}
}
I've recently started using Xcode and Beginner to creating apps. I've come across something I'd like to implement but research hasn't been quite clear/complicated to understand.
I have a TableView with Days of Week and also a segmentedControl that duplicates these days 3 times. I'm wondering how I'm able to get user click to take me to an alternative ViewController depending on which day it is and what segment of the segmentedController is selected without having to create 21 viewcontrollers in the storyboard.
I've used a ViewController and made an outlet to a tableView for this setup.
in you tableview delegate method -> didSelectedRowAtIndexPath
you can simply write
let vc = UIViewController()
/*
you can add informations here
*/
present(vc, animated: true)
and inside this method you can use the indexPath to get the cell you've clicked
let cell = tableView.cellForRowAt(indexPath)
now you can get the information in this cell
You can have one viewcontroller which is basically a recipe for the viewcontroller you want to go to.
For example you want to show a viewcontroller with a label that states a combination of the number from the segmented control and the date which the user tapped on.
If you now create a ViewController which has a label in storyboard, the text on the label doesnt matter, you can use code to change the text to anything you would like.
In the tableviewcontroller you can use the didSelect delegate method of your tableview to present the viewcontroller and set the label to the values of the segmented control and the cell which is tapped.
I think you just need some more information about iOS and programming in general, therefore I suggest you watch the following iTunes U course:
https://itunes.apple.com/us/course/developing-ios-10-apps-with-swift/id1198467120
It has everything you need to know
Create a detail view controller with two variables (Ex - dayName and selectedSegmentIndex). And in your current viewController "tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)" push detailsViewController with these details like this
let objViewController: DetailsViewController? = UIStoryboard.mainStoryboard().instantiateViewController(withIdentifier: "DetailsViewController") as? DetailsViewController
objViewController?.dayName = dayName
objViewController?.selectedSegment = segmentControl.selectedSegmentIndex
navigationController?.pushViewController(objViewController ?? UIViewController(), animated: true)
I've been trying to create table view cells each with a UIImageView serving as a background for them. However, when I tap on each cell the table view will not register the click and will not transition to the view controller I have hooked up, even while I'm using the didSelectRowAtIndexPath function.
I realize it's probably an issue with the ImageView obstructing the table views ability to register the cell tap. The cells will transition however when I drag my finger/mouse on it from left to right, just not on taps. I tried to use a Tap Gesture Recognizer on the Image View however it only worked for the cell at the very top and not all of them. How do I tackle this issue?
Here is an image of the table view cells so you have an idea of what I'm working with: http://imgur.com/a/Ku4uD. Thank you!
If you uncheck User Interaction Enabled on your Image View, the problem should be solved. When running into a problem always check the user interaction of the most child view and work your way up.
One trick I have also learned is to create a subclass of a child and override touchesShouldCancel like so:
override func touchesShouldCancel(in view: UIView) -> Bool {
print("touchesShouldCancel")
//Run extra code that you want when the user selects this view
//then still retrieve the tap by its parent.
return false
}
I am unsure of exactly what your problem is, but I would delete whatever segue that you have, add a new one by dragging from the yellow circle on the left side of the center portion of the top of your tableView ViewController inside the storyboard, to the viewController that you desire it to segue to. Give the segue an appropriate identifier, and then inside your tableView class under tableView didSelectRow add performSegue(withIdentifier: "ChosenIdentifier", sender: indexPath)
Then in prepare forSegue add in:
if let vc = sender.destination as? TheViewControllerYouAreSegueingTo {
if let indexPath = sender as? IndexPath {
vc.variableIdentifyingWhatCellWasClicked = indexPath.row
}
}
with whatever adjustment is needed to meet your specific needs.
I'm creating an app which shows data in a UITableView. This data also contains location information, so I want to add a MapView to display this data. When a user taps a UITableViewCel, I need to segue to another UITableView to show the detailed data. I still want to show the MapView with the same data above this detailed data, and I still want the NavigationBar to update, i.e. the back buttons returns the user to the first UITableView.
In image form to make it easier to understand
I was thinking of making a subclass of a UINavigationController and putting the container underneath the MapView, but I don't really know where to go from there.
Have VC0 embedded in a navigation controller or subclass UINavigationController. Create an Info ViewController and push that on the navigation controller.
In your particular case you'll want to use the didSelectRowAt method from UITableViewDelegate.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// use indexPath.section and indexPath.row to use your data
let infoVC = yourInfoViewController()
infoVC.title = "Info Cell Name"
navigationController?.pushViewController(infoVC, animated: true)
}
Edit after first comment:
I'm not sure what the best way of doing this is but one way you can do it is:
Modify your table view based on what is being shown, ie: first set of data or cell detail data
Update the navigation bar's title and left bar buttons per set of data you're displaying
One of those buttons will only appear in the cell detail data set and it sets your switch back to displaying the first set of data
I'm currently creating an iOS app in Swift 1.2 with a master-detail UITableViewController setup so that MasterTableViewController has cells that push to DetailTableViewController.
DetailTableViewController has fairly complex cells that pull data from a web client to generate a chart, similar to in Apple's Health app. It usually takes about 5-10 seconds for all the data to download.
As a result, there is a 5-10 second delay when a cell in MasterTableViewController is tapped before DetailTableViewController is shown.
I would ideally like to push immediately from the MasterTableViewController to the DetailTableViewController and then display an activity indicator on the DetailTableViewController page that is dismissed when all the data is downloaded.
Could someone point me in a good direction to accomplish this? Thank you! :)
My code is below for pushing from master to detail. Fairly basic. I feel like if I change something in the viewDidLoad or cellForRowAtIndexPath method, I could get this done fairly easily.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: false)
let detailVC = DetailTableViewController()
detailVC.navigationItem.title = "Your Charts"
self.navigationController?.pushViewController(detailVC, animated: true)
}
On your detail view controller you can create a UIActivityIndicatorView variable.
In viewDidAppear you can call the activity indicator, bring it to front and start animating it.
The create a function that populates an array that will store the data your cells will use and re work your cellForRowAtIndexPath to use it. (Instead of fetching the data in each cell).
Then in your function to fetch data, right after (or before) you update your table tell the activity indicator to stop animating.