I have a view controller that is called from 2 different places.
1) I call it from a root controller. It is shown and populated. The add button works perfectly. I open a modal form, get the information and return it to the view controller via it's delegate.
- (void)itemsAddViewController:(AddItemView *)itemsAddViewController didAddItem
(OrdersDetails *)orderDetail;
{
if (orderDetail) {
[orderDetailItems addObject:orderDetail];
}
[self fetchOrderDetails];
[lineItemsTableView reloadData];
[self dismissModalViewControllerAnimated:YES];
}
However, when I call it from another view (on the right side of the split view), this same code does NOT reload the table. It adds the data -- if I leave the form and come back, the data is there, but the tableview is not being refreshed. When I step through the code, it gets the the line, but then goes over it like it doesn't see it.
When a modal view controller is presented over the view controller containing -itemsAddViewController:didAddItem: the underlying controller's view is not visible and will therefore be unloaded if the controller receives a memory warning.
As a result your view may not be loaded and your lineItemsTableView outlet may be nil when you call -itemsAddViewController:didAddItem:. Your call to reloadData would need to move to -viewWillAppear: to avoid assuming that your controller's view can have a persistent state when it is not visible.
Related
So I tried everything with showing up the back button but it just won't work
This is how i arrange my View Controllers Used segue show from view controller to site view controller
And here is the site view controller that isn't showing back button
I even tried adding NavigationBar and a button with this function
self.navigationController.popToRootViewControllerAnimated(true)
Also failed
Update:
I tried this in both view controllers it's returning nil
in viewDidAppear and viewWillAppear
print(self.navigationController?.restorationIdentifier)
Once I got the same problem, when I was try to use view property of my UIViewController before it loaded properly. This caused problems with loading my navigation bar items. In fact, you should not touch view property until viewDidLoad method is called. Check, maybe it is your case, maybe you use view property in prepareForSegue method or in observers?
In Apple's developer documentation, the property presentedViewController in UIViewController is described as "The view controller that is presented by this view controller, or one of its ancestors in the view controller hierarchy". It is confusing. What does "its ancestors" mean?
This question is really old, but it was still the top Google hit for my search, and the existing answer is wrong and makes things even more misleading.
This property always returns a presented view controller (or nil), it will never return an ancestor view controller. What the reference to ancestors means is that if the view controller you call it on isn't presenting any view controller itself then it will walk up the hierarchy to see if any parent view controllers are presenting anything.
For a concrete example - let's say you have ContentViewController which is a contained within a UINavigationController. The NavigtionController is currently presenting another view controller (perhaps a UIAlertViewController for example).
In this case the presentedViewController property of both the ContentViewController and the NavigationController will return the UIAlertController that is being presented by the NavigationController. When this is dismissed it will return nil for both of them.
So to add a bit more clarity to the line in the Apple Docs:
"The view controller that is presented by this view controller, or [the view controller presented by] one of its ancestors in the view controller hierarchy."
There are two view controllers, viewA and viewB. viewA presents viewB. Now this is what the documentation is referring to:
Example 1 ( calling viewA.presentedViewController )
This will return viewB, because viewA presented viewB
Example 2 ( calling viewB.presentedViewController )
This will return viewA because viewA is an ancestor of viewB. In other words, imagine these two views in a line. viewB is second in line while viewA is first. So a view's ancestor is the view behind itself.
Only reason why this function call on viewB returns viewA is because viewB did not present any other view controller. Or in other words, viewB is on the top of the hierarchy. There is no view in front of viewB.
My root view controller is an UISplitViewController, which has a UITableViewController as master view controller. On iPhone (compact width), it looks like a UINavigationController.
Tap a cell to show detail view controller
Tapping the trash button would delete the current note. My problem is how to go back to the master view after that? Since it's an UISplitViewController, it can't pop the current view controller as UINavigationController does.
I had a similar problem and finally found a solution. As I understand it, when in compact width, the detail navigation controller becomes a view controller of the master navigation controller. So all you have to do is:
Determine if only one view is present by checking the split view controller's collapsed property. If it isn't collapsed (e.g. on iPad), you're already showing the table view in addition to the detail view.
If it is collapsed (e.g. on iPhone) get a reference to the master navigation controller via the detail navigation controller and have it pop to its root view controller which, in this case the your table view controller.
This is the code I use in my detail view controller. In your case I think you just need to add this code to the button action in your detail view controller:
if splitViewController!.collapsed {
let detailNavController = parentViewController as UINavigationController!
let masterNavController = detailNavController.parentViewController as UINavigationController!
masterNavController.popToRootViewControllerAnimated(true)
}
Good luck!
I have a project where a user fills in a web form, once the user hits submit it moves to a viewcontroller that shows a message "sent" or "error".
How can I make it automatically move to the main view controller without pressing a button, after a certain amount of seconds (so it displays the message "sent" for approx 2 - 3 seconds then moves to the main vc)
Any information would be highly appreciated, thankyou
Sean
You should be able to show the view and, in the viewDidLoad method (or viewDidAppear), set a timer to call a method that dismisses the view controller. Use performSelector:withObject:afterDelay to perform the delay.
Have a look here:
How do you trigger a block after a delay, like -performSelector:withObject:afterDelay:?
You can trigger some code inside a block to run after a specified delay. Inside that code you can include your code to navigate to the other view controller.
The code for doing this depends on whether you are using storyboards or not. If you are using storyboards, you can use:
[self performSegueWithIdentifier:#"MySegueName" sender:self];
If you are not using storyboards, you can use the following to display the second view controller modally:
[self presentModalViewController:myNewViewController animated:YES];
(Abstract: bindings work in code, but not in IB)
I have a window managed by a NSWindowController. To the left of the window is a source view. To the right is a table view showing the elements of the currently selected source.
I have set up a NSTreeController within my window XIB. I want its contents to be used for the source view. It's selection will drive the table view.
I am trying to split this up using NSViewControllers. One view controller will load a NIB containing the source view. Another view controller will load the table view.
Seeing that I need access to the NSTreeController within the source view controller, I have set it to be the view controller's representedObject. (Actually for this setup to be done by the time awakeFromNib is called on the view controller, I have turned representedObject into an IBOutlet).
All works fine when I wire my source view up in code:
[outlineView bind:#"content"
toObject:sources
withKeyPath:#"arrangedObjects"
options:nil];
[outlineView bind:#"selectionIndexPaths"
toObject:sources
withKeyPath:#"selectionIndexPaths"
options:nil];
[[outlineView tableColumnWithIdentifier:#"Title"] bind:#"value"
toObject:sources
withKeyPath:#"arrangedObjects.title"
options:nil];
I am however unable to reproduce this using Interface Builder. Thing is, here the "controller key" textfield is grayed out. Thus I bind column's "value" to the file owner using a model keyPath of "representedObject.arrangedObjects.title". This does not show the desired behavior. Actually an exception is thrown: -[NSProxy doesNotRecognizeSelector:_mutatingNodes] called!
How can I use representedObject in IB?
Can I create a controller in IB which acts as proxy to representedObject?
Could I set-up a tree controller in the source view XIB which during NIB loading gets swapped out for the representedObject?
I moved away from using representedObject. It appears that is meant only for model objects.
I now pass in my tree controller using a custom outlet. I continued setting up and tearing down the bindings in code.
I’ve similar issues when I try to pass a reference to an object controller (NSTreeController in my case). I don’t think this is how Apple wants you to use their KVO-compatible controllers. The exceptions look like they’re XIB-unarchiving & timing-related.
The trick is not to pass the controllers, but to pass the underlying data and keep the selection in sync.
This way you can set up your bindings in a storyboard and won’t get any exceptions. You’ll have to set up a new instance of an object controller for every child view controller (copy & paste in Storyboard once you configured the first one works). For a detailed example take a look at another answer that gets much more into detail.