What UINavigationController event can be overridden to get access to current view controller? - xamarin.ios

What UINavigationController event can be overridden to get access to current view controller?
My end goal is to check the current screen in the Navigation Controller to determine whether or not to call SetNavigationBarHidden.

If by "current" you mean "currently visible" you can make use of UINavigationController's VisibleViewController property. Though if you're using MT.D you'll want to cast it out:
var currentViewController = (DialogViewController)myNavController.VisibleViewController
Alternatively you could access the ViewController array directly. Or...you can also subclass DialogViewController and set the NavigationBar.Hidden = true inside the implementation.

How about having a UINavigationController subclass adopt the UINavigationControllerDelegate protocol? Then implement the monotouch equivalent of navigationController:willShowViewController:animated: or navigationController:didShowViewController:animated:. Each of these methods passes a parameter which is a pointer to "[t]he view controller whose view and navigation item properties are being shown." You'll have to remember to make the navigation controller its own delegate.

Related

CosmicMind: How to transition between controllers within a container view using Motion

I try to implement the Motion feature with transition from one view controller to another when they are used in a container view.
This is what I want to achive:
Using a UIViewController that includes a container view,
Set the container view with a view controller that includes a table
When user selects the row, I want to transition to another view controller and at the same time animate the image in the table view to the image in the new viewcontroller.
So I have the following UIViewControllers:
Main UIViewController, with a containerView
List UIViewController
Detail UIViewController
No I want to cycle, the list view controller with the detail, with a transition of the image.
Kind of like the PhotoCollectionSample, but within a container view.
I have set the isMotionEnabled = true in the main view controller and the view controllers used in the container. I also have set the same motionIdentifier on the imageViews in both view controllers.
The issue I'm facing is how to transition between the controllers. Since I'm not using the UINavigationController or UITabBarController I don't think the animation is triggered.
At the moment I'm transition between controllers by using the implementation found here.
Switching Child View Controllers in iOS with Auto Layout
But I think I have to do it in another way.
Use this method
/**
A helper transition function.
- Parameter from: A UIViewController.
- Parameter to: A UIViewController.
- Parameter in view: A UIView.
- Parameter completion: An optional completion handler.
*/
func transition(from: UIViewController, to: UIViewController, in view: UIView, completion: ((Bool) -> Void)? = nil)
and call it like this:
Motion.shared.transition(from: vc1, to: vc2, in: container)
That should work :)

MonoTouch.Dialog: Dismissing a Keyboard

Using the Reflection API to auto generate a UI.
How can I dismiss the keyboard when the user selects a new field, or if they choose a field which generates a new view to pick from. In the later case, when the user returns to the first screen, the old keyboard is still there.
UIView.EndEditing(bool force);
The above will hide the keyboard for you without needing to know who the first responder is. I haven't done much with the reflection API but you should be able to call that on the view when an element is selected.
Apple Docs -- endEditing:
Clarification for those initially struggling with the MonoDialog portion of the question:
The EndEditing method is not available on DialogViewControllers objects directly (who inherit from UITableViewControllers). You should be calling EndEditing(bool) on the View of a DialogViewController and not trying to call EndEditing(bool) on the actual DialogViewController itself.
For clarification:
DialogViewController dc;
dc.View.EndEditing(true);
Note:
UIView objects include the EndEditing(bool) method, but UITableViewControllers do not inherit from UIView so the EndEditing method is not available on the controller itself. UITableViewControllers contain a view object, call EndEditing on that view object.
Check the ResignFirstResponder method. This one should help you I guess.

Getting UITabBarController to work with Core Data

I've been reading this thread on Stackoverflow and have been trying to replicate the solution with no success in my own project.
My project has 4 tabs. In my app delegate I do this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
Page1 *page1 = (Page1 *)[navController topViewController];
Page2 *page2 = (Page2 *)[navController topViewController];
Page3 *page3 = (Page3 *)[navController topViewController];
Page4 *page4 = (Page4 *)[navController topViewController];
page1.managedObjectContext = self.managedObjectContext;
page2.managedObjectContext = self.managedObjectContext;
page3.managedObjectContext = self.managedObjectContext;
page4.managedObjectContext = self.managedObjectContext;
[self.window makeKeyAndVisible];
return YES;
}
In the originating thread it says I need to create a IBOutlet to each navController for each tab I want to use Core data on.
Whilst you can assign multiple delegates for the UINavigationController the same is not true for the outlets, you can only ever supply ONE outlet for the navController.
I can get Page1 to work, but the other pages simply crash; because of the lack of an IBOutlet.
Do I really need X IBOutlets for Y Tabs or can I do it another way?
Another issue is that the originating thread the accepted answer is:
Ideally you want to pass either the
NSManagedObjectContext,
NSFetchedResultsController or the
relevant NSManagedObject "down" into
the UIViewController.
But there is no code or example of how to do this.
Ideally, I do not want to use a singelton or use the app delegate all over the place.
Any confirmation and clarification would be great.
Thanks.
Your immediate problem has nothing to do with Core Data. You are assigning the same navigation controller to each tab when you need a separate navigation controller for each tab otherwise the navigation controller's hierarchy of views will get scrambled every time you change tabs.
The pattern recommended in the question you linked to is called "dependency injection" and it is the one that Apple recommends in most cases. However, in the case of tabbars or any other complex view/view-controller hierarchy, dependency injection can get to complicated. It's a particular issue with tabbars because you don't usually load all tab view/view-controllers when the app starts but wait until each tab is selected before loading its elements.
Instead, you can use an alternative pattern that exploits the UIApplication objects singleton status. Since there is only one application object, there is only one application delegate object. That means that anywhere in the app you can make a call like this:
(MyApplicationDelegate *) appDelegate=(MyApplicationDelegate *)[[UIApplication sharedApplication] delegate];
... and always get the same application object. Then, if you have the managed object context defined as a property of the app delegate you can get the context just by:
theManagedObjectContext=appDelegate.managedObjectContext
Add these two lines to every view controller and you can always be sure of getting the app delegate's managed object context.

MVC basics: Should I add a UIViewController, a Delegate or a Source to my custom view?

my question is about view controllers, delegates and all that in general. I feel perfectly comfortable with UIView, UIViewController, Delegates and Sources, like UITableView does for instance. It all makes sense.
Now I have implemented my first real custom view. No XIBs involved. It is an autocomplete address picker very much like in the Mail application. It creates those blue buttons whenever a recipient is added and has all the keyboard support like the original.
It subclasses UIView. There is no controller, no delegate, no source. I wonder if I should have either one of those? Or all, to make it a clean implementation.
I just cannot put my finger on the sense a view controller would make in my case. My custom view acts much like a control and a UIButton doesn't have a controller either.
What would it control in my view's case?
Some of my thoughts:
For the source: currently the view has a property "PossibleAutocompleteRecipients" which contains the addresses it autocompletes. I guess this would be a candidate for a "source" implementation. But is that really worth it? I would rather pass the controller to the view and put the property into the controller.
The selected recipients can be retrieved using a "SelectedRecipients" property. But views should not store values, I learned. Where would that go? Into the controller?
What about all the properties like "AllowSelectionFromAddressBook"? Again, if I compare with UIButton, these properties are similar to the button's "Secure" property. So they are allowed to be in the view.
The delegate could have methods like "WillAddRecipient", "WillRemoveRecipient" and so on and the user could return TRUE/FALSE to prevent the action from happening. Correct?
Should I maybe inherit from UIControl in the first place and not from UIView?
And last but not least: my custom view rotates perfectly if the device is rotated. Why don't all views? Why do some need a controller which implements ShouldAutoRotateToDeviceOrientation()?
Does it make sense what I wrote above? In the end I will provide the source on my website because it took me some time to implement it and I would like to share it as I have not found a similar implementaion of the Mail-App-like autocomplete control in MonoTouch.
I just want to learn and understand as much as possible and include it in the source.
René
I can answer part of your question.
I just cannot put my finger on the
sense a view controller would make in
my case
The ViewController is responsible for handling the View's state transitions (load, appear, rotate, etc) These transitions are used mainly when you use a navigation component (UINavigationViewController, UITabBarController). These components needs to received a ViewController that will handles the view's transitions.
For exemple, when you push a ViewController on a UINavigationViewController, it will cause the ViewDidLoad, ViewWillAppear, ViewDidAppear. It will also cause the ViewWillDisappear, ViewDidDisappear of the current ViewController.
So, if your application has only one portrait view, you don't need a ViewController. You can add your custom view as a subview of the main window.

Updating an AnnotationView Callout after details entered in View Controller that was pushed form the map view

I have a simple maps app with multiple pins on a map view. My intention is to tap a pin, show a callout with an accessory view, push to a Detail View Controller where you can edit that pin/locations details. This all works fine, but once i pop the Detail View Controller the callout on the map view is still there, which i want, but it still has the old uneditied values. How can i refresh/update the callout view once the Detail View Controller is popped?
I am using Core Data with a simple database. I have tried using controllerdidchangecontent, Map View Controller Will Display methods etc but my main problem is identifying which object has been added/updated/deleted and which is the corresponding callout/selected pin.
Any help appreciated...
Not sure if you had find your answer but the way to do it is to extend MKAnnotation class and creating custom annotation and passing them while creating placemarks. Later you can get them from MKAnnotationView's annotation property.
See a good implementation here
http://www.slideshare.net/360conferences/getting-oriented-with-mapkit-everything-you-need-to-get-started-with-the-new-mapping-framework
The only way I could find to update the callout info was to mess directly with the subviews of the callout.
The callout view is the first subview of the annotation view.
In the following example, I update the subtitle.The title label is the 6th and the subtitle is the 7th subview of the callout:
if (myAnnotationView.subviews.count > 0)
((UILabel*)[((UIView*)[myAnnotationView.subviews objectAtIndex:0]).subviews objectAtIndex:7]).text = #"Some example";

Resources