SplitView - reload data in master tableView based on detail changed in swift - ios

I create splitView with tableView in master View and tableView with static cells in two details view (see on picture).
App Structure
Names of view controllers are:
DocsTableViewController - master view (on the left)
DocDetailTableViewController - detail view (on the top right)
DocEditTableViewControler - second detail view (on the bottom right)
DocsTVC is list of doctors, DocDetailTVC is detail of doctor user selected in DocsTVC and on DocEditTVC user can edit data of doctor showed in DocDetailTVC or add completely new one (based user clicked on edit or add button).
All these things are working fine - show detail, show edit form and save edited or new doc. Problem is the master table view. I'm trying to reload it in detail after saving edited/new item and by print I see that data are reload but not the table. Table is showing still the same and I have to go to same other screen of app and then go back to see reloaded table view. What should I do?
After saving doctor on DocEditTVC I'm going back to detail to this method:
#IBAction func saveToDocViewController (segue: UIStoryboardSegue){
let controller = DocsTableViewController()
controller.tableView.reloadData()
print("[SPLIT VIEW] detail: \(controller.docs.count)")
}
And some codes from DocsTableViewControler (the master view):
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
// menu
if inputsMenuButton != nil {
inputsMenuButton.target=self.revealViewController()
inputsMenuButton.action=#selector(SWRevealViewController.revealToggle(_:))
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
// navigation bar
self.navigationController?.navigationBar.barTintColor = OAKScolor().colorOAKSmain()
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]
// data load
print("[SPLIT VIEW]: ViewDidLoad")
dataLoad()
self.tableView.reloadData()
// split view
self.splitViewController?.delegate = self
self.splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.AllVisible
}
and
func dataLoad() {
print("[SPLIT VIEW]: DataLoad")
let arrayOfDocIDs = PlistManager.sharedInstance.getArrayOfValuesFromDict("DocID") as [AnyObject] as! [String]
for id in arrayOfDocIDs {
docs.append(DocData(docID: id).docLoad(false))
}
print("[SPLIT VIEW] table: \(docs.count)")
}
By these prints I see that evening is going well - view did load on the master view and array of docs write new count. But the tableView is not changed. Thank you for any help.

With this code
let controller = DocsTableViewController()
controller.tableView.reloadData()
You created new Master controller instance, not the current one.
There is 2 ways to solve it:
In Detail Controller, create a reference to current master controller.
Use Delegate. Here is a good explanation:
https://www.natashatherobot.com/explaining-ios-delegates-a-story-about-your-morning-coffee/#
Hope this help!

Related

UITableViews as pick lists

I have a view controller with 2 labels - each to be populated from lists in 2 separate table controllers. In my view controller I have 2 variables (temp and temp_1) to receive the data from the table controllers and populate the labels.
When I call the first table view and select an item that works fine and my first label is populated, when I then call the second table view that works too and my second label is populated - except that the first label is now blank - because temp is now blank.
I have attached my prepareForSegue from my first table view showing me passing my variable temp back to my view controller. (My second is similar and passes back temp_1)
Thanks for any help.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "return_1" {
if let destination = segue.destinationViewController as? main_ViewController {
if let row = tableView.indexPathForSelectedRow?.row {
destination.temp = array1[row] as! String
}
}
}
}
My guess is that what you are saying in words is not what in fact you are actually doing. You say "back to my view controller", as if you were returning from the table view to the main view controller. That is what you want to do and what you should do, but it isn't what you're doing (I'm guessing). I think you've set up your storyboard with a normal segue from the table view to the main view controller. That doesn't go back; it makes a whole new main view controller. So of course the old label value is missing, because this is a different view controller from the one with the old label value (which effectively is still there, two layers down, covered up by this new instance).
What you want is an unwind segue. That is how you say "go back" in a storyboard.

Where to place code to populate a UITextfield (title field) after a segue screen returns to main screen?

I am building a Swift - Single View app. I’ve added a “segue" view to allow user to store a title line preference using NSUserDefaults. When I return to the primary view the title line isn’t filled with the new title info from NSUserDefaults. I’ve placed the code to populate the main screen title line in the viewDidLoad section noted below. Strangely enough, if I go to the “segue" screen and back to main screen again without making changes then it shows up. Where can I place code to get the title line stored in my preferences segue screen to show up when I go back to the main view? Here is my code that works, but only after going back and forth from the seague twice. Thanks for any help.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let defaults = NSUserDefaults.standardUserDefaults()
let titlePref = defaults.objectForKey("usertitleLineKey")!
titleLine.text = titlePref as! String
}
You should use viewWillAppear or viewDidAppear callback methods to refresh any content in your view when or just before it shows up. viewDidLoad will only be called once when the view is initialised on to memory.
Try this code:
override func viewWillAppear() {
let defaults = NSUserDefaults.standardUserDefaults()
let titlePref = defaults.objectForKey("usertitleLineKey")!
titleLine.text = titlePref as! String
}

navigating through desired views (while skipping some views) using UINavigationBar back button

I am using a UICollectionView to show a list of images.
1)By clicking on any cell the image and some description about it is displayed in the resulting view controller(using a push segue).
2)When i swipe from the left/right edge(using PanGesture) i need to display the details of the previous/next image in the collection view.
3)But the back button of the navigation bar has to take me back to the collection view and not to the previous displayed details (shown by the PanGesture).
I know how to get 1 and 2 done but don't have a concrete idea to get the 3rd job done.
Any help would be appreciated.
You can find your desired UIViewController in your navigation stack using for loop. Try this. This is in Swift
for (var i = 0; i < self.navigationController?.viewControllers.count; i++) {
if (self.navigationController?.viewControllers[i].isKindOfClass(YourViewController) == true) {
println("is sw \(self.navigationController!.viewControllers[i])")
(self.navigationController!.viewControllers[i] as! YourViewController)
self.navigationController?.popToViewController(self.navigationController!.viewControllers[i] as! YourViewController, animated: true)
break;
}
When you navigate from one view to another (e.g. by showing a detail view of your images one after the other, then all these views are internally piled up as a stack.
Thus, if you want to jump directly to a view somewhere in between this stack (e.g. the collection view), then you can use the Unwind Segue.
In your case it should work like this:
First, in your collection view (i.e. your back button destination) you need to implement a UIStoryboard Segue as follows
#IBAction func myGoBackPoint(segue: UIStoryboardSegue) {
println("Jump directly back here from any other view")
}
Then, in the storyboard of your detail view you ctrl-drag directly to top rightmost Exit marker and choose the previously created back button destination:
In the code of the detail view implement the "go back instruction"
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "My Unwind Segue" {
if let myUnwindSegue = segue.destinationViewController as? MyCollectionViewController {
// prepare for segue
}
}
}
Hope this helps.
Finally after researching a lot i found that using a collection view with each cell taking up the whole screen is the best way to go about solving this issue.
Thankyou

Why does initializing a view controller with nibName not set the new instance as file owner?

I am trying to display one view or another view inside the detail view of a master/detail based on a conditional.
These views will contain outlets and elements, so I would like to have view controllers for each that I can play with.
So I created a new UIViewController called AddPhotoViewController. This is how I add AddPhotoViewController.xib inside DetailViewController:
let photoVC = AddPhotoViewController(nibName: "AddPhotoViewController", bundle: nil)
let photoView = photoVC.view
photoVC.delegate = self
photoView.autoresizingMask = UIViewAutoresizing.FlexibleWidth
photoView.frame = area.bounds
area.addSubview(photoView)
The view loads properly in the detail view and looks like this:
AddPhotoViewController.xib's owner class has been set as well here:
When I tap the button, though the action is set properly in AddPhotoViewController to print a message, Xcode crashes.
Am I doing this correctly? Is there a more common practice for loading view X or view Y inside a view controller depending on user data?
Button action:
#IBAction func ButtonPressed(sender: AnyObject) {
println("worked!")
}
Button connection:
Console output:
I think you need to add the viewController:
addChildViewController(PhotoVC)
//and then
PhotoVC.didMoveToParentViewController(self)

Swift selecting rows in TableViewController and opening up a ViewController

I started learning App development in Swift recently and I'm still fairly new. I'm trying to make an app where at the home screen, the user will click a button called profiles, and it'll show a list of names in a tableViewController. When the user clicks a name it'll open up the person's profile in a viewController.
I'm stuck so far on what method and what to code in that method to allow the user to click on the list of names in my TableViewController and then open up a viewController for that person. I've already created my other viewController (DetailsViewController) and created a segue between the TableViewController and the DetailsViewController.
I've been searching for a long time on how to do this but couldn't find any luck. If someone could just point me in the right direction that'd be great.
You have to create the segue from the cell to the detail view controller. To provide the detail controller with the data, give it a property (e.g. name) that you can set in prepareForSegue which you override in the parent controller.
override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
let cell = sender as UITableViewCell // or your cell subclass
let indexPath = self.tableView.indexPathForCell(cell)
let name = dataArray[indexPath.row]
// or something else depending on the structure of your data model
let controller = segue!.destinationViewController() as DetailViewController
controller.name = name
}
The detail view controller can now populate its view with the passed information.

Resources