UIModalPresentationFullScreen not working in iPad landscape mode? - cocoa-touch

I have added a ViewvController(B) as subview on ViewController(A). In ViewController A(SuperView) UIModelPresentationFullScreen working fine. But when am calling UIModelPresentationFull in ViewController B(SubView) it modelview showing in Portrait mode and that is also not fully viewed. How to solve this problem. Can any one help me please. I have tried 2 days.
This is what I tried in both the superview and subview...
picFBCapture *fbCapt = [[picFBCapture alloc] init];
//[self.navigationController pushViewController:fbCapt animated:YES];
//fbCapt.modalPresentationStyle = UIModalTransitionStyleFlipHorizontal;
fbCapt.modalTransitionStyle = UIModalPresentationFullScreen;
[self presentModalViewController:fbCapt animated:NO];
[fbCapt release];
Thanks in advance..

The problem is that if you add a view controller as a subview it's not connected to the view controller hierarchy and thus certain things doesn't work. You should avoid adding view controllers as subviews whenever possible, since this is not how Apple intend view controllers to be used, but sometimes it can't be avoided.
If this is one of those cases when it can't be avoided you should save a reference to view controller A in view controller B and then call presentModalViewController: on view controller A (that is connected to the view controller hierarchy) instead of self (view controller B, that isn't connected).
EDIT: In controller A you probably have code looking something like:
[self.view addSubview:controllerB.view];
In conjunction to this line add:
controllerB.controllerA = self;
I hope you know how to create properties, but if not here's a hint:
#property (nonatomic, assign) UIViewController *controllerA;
The rest you should be able to figure out using Google and the documentation.

You will have to handle viewController B's view in landscape by yourself. Since viewController B has been added as a subview, its view controller will not be handling its landscape orientation. The UIModalPresentationFullScreen style (landscape and portrait) will work only if viewController B is shown, ie not as subview but as a full view itself.

Related

tvOS preferredfocusedview is not always called

After a viewcontroller has been presented modally, the initial preferredfocusedview is called. However, after we dismiss the viewcontroller and it has been dealloc. preferredfocusedview is not called after presenting the viewcontroller again. Running on tvOS 9.2.
Even adding the following did not help:
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self setNeedsFocusUpdate];
[self updateFocusIfNeeded];
}
Anyone know what's going on? Or if there's anyways to debug this?
Edit:
the way I am adding the viewcontroller:
viewController = [[UIViewController alloc] init];
[viewController addChildViewController:self];
[viewController.view addSubview:self.view];
[self didMoveToParentViewController:viewController];
If you are using a container view, having multiple ViewControllers or adding only one View Controller, the preferredFocusEnvironments method must be called from the rootView Controller indicating which View Controller to focus.
For eg.
View Controller A has a container View having ViewControllers B and ViewController C inside the Container.
View Controller A should have preferredFocusEnvironments returning which ViewController to focus.
This way, preferredFocusEnvironments on ViewController B or ViewController C will be called whenever the view becomes visible.
If the ViewController A doesn't have preferredFocusEnvironments, then it won't be called on the containerView ViewControllers.
Implementing custom focus behavior in tvOS 9 is disaster. Apple already mentioned that there is a limitation on redirecting focus specially when presenting/ dismissing a viewcontroller in WWDC.
tvOS10 will handle munch better with preferredFocusEnvironments.
https://developer.apple.com/videos/play/wwdc2016/215/
When I needed to fix this focus redirection issues in viewDidAppear in tvOS 9, I had exactly same issues. Sometimes it works, sometimes not. No clue what so ever. But after I put split second delay on setNeedsFocusUpdate / updateFocusIfNeeded in viewDidAppear it was way better in terms of consistency. preferredFocusedView get called all the time.
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self setNeedsFocusUpdate];
[self updateFocusIfNeeded];
});
}
Do this in both presented and presenting view controllers, if you are manually changing focus. This is all from my observation and I don't think there is a proper way to achieve some focus behavior because tvOS API is kind of new and premature. Sorry about not being able to give you good explanation why this might work. Good luck.

Add UITableViewController to other View

Is it possible to embed (add as subview) a UITableViewController into another View Controller programmatically? I found a few answers here on StackOverflow but none worked for me with ARC and iOS6 SDK.
I know you can do this easily with Navigation and TabBar controllers but I am more curious about adding tableviews to a regular View controller. I need my tableview to occupy the lower part of the available screen space (I need the rest for other purposes, for which neither tab nor navigation types are suitable).
When I tried to do it, however, it did not work. I instantiated a subclassed UITableViewController, but when I added it to my self.view as a subview, the compiler said I tried to use "incompatible pointer types." Not only that, my instantiated UITableViewController does not have a .frame property, so I cannot set it dimensions, which would be the whole point of this exercise.
Building upon ogres answer, you should add the tableViewController's view as a subview, but it is not everything. The tableViewController is a viewController and it needs to know its parent and its children, to do its viewController-job correctly. I do not know any details here, but there is an entire talk about this from WWDC 2011 called "Implementing UIViewController Containment".
One problem I have experienced when only adding the view as a subview is that target actions don't seem to work. Tapping a UIButton or similar causes either a EXC_BAD_ACCESS or a unrecognized selector sent to instance.
So I recommend that you do something like this:
UIViewController *vc = //Your tableViewController
[self addChildViewController:vc]; //Important
[self.view addSubview:vc.view];
//If you want to set the frame, set the frame of the tableViewController's view
vc.view.frame = ...
yes , you can use tableview in another view without any problems
UITableViewController, but when I added it to my self.view as a subview
are you trying to add viewcontroller as subview or its view ? ( viewcontroller.view )
UITableViewController does not have a .frame property,
of course it does not have .frame property , it is a view CONTROLLER , you should see .view.frame

Is this the right way to add a view?

I make a program that shows a table.
If people click the search I will add another view covering the original view. The original view is [BNUtilitiesQuick listnewcontroller];
[[BNUtilitiesQuick window] addSubview:[BNUtilitiesQuick searchController].view];
[[BNUtilitiesQuick searchController] viewWillAppear:YES] is indeed called. So it seems that UIView has a pointer to it's controller
However, the view that the [[BNUtilitiesQuick listnewcontroller] viewWillDisappear] is not called
Moreover, [[BNUtilitiesQuick listnewcontroller] viewWillAppear] is also not called even when the user has finished modifying search term with this code:
[self.view removeFromSuperview];
I think I may be missing something here. What exactly should I do anyway so IOs knows that the searchController.view will be covering listNewController?
This is NOT the right way to do it. If the searchController is a full screen controller you should present it modally using presentViewController or push it onto the navigation stack as #StuR suggested.
In case your search view covers only part of the listnewcontroller you should use the containment API in iOS5.
Inside listnewcontroller (parent view controller) you would write:
[self addChildViewController:self.searchController];
[self.view addSubview:self.searchController.view];
[self.searchController didMoveToParentViewController:self];
For more in-depth information check out the WWDC 2011 session video "Implementing UIViewController Containment". Also watch "The Evolution of View Controllers on iOS" from 2012 because there are some changes and deprecations in iOS6.
ViewController *viewController = [[ViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
I'd consider using pushViewController for adding a full screen view. addSubview is for views that don't cover the entire screen.
viewWillDisappear and viewWillAppear will only me called if you pop or push the given viewController. You are simple adding a subview with it's own viewController inside(on top) of the present viewController. As StuR said, if you want to dismiss the current ViewController you should use:
BNUtilitiesQuick *searchController = [BNUtilitiesQuick alloc] init];
[self.navigationController pushViewController:searchController animated:YES];
You can read more about ViewControllers here: http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007457

Replacing Storyboard Segue with pushViewController causes strange behaviour

I can't seem to figure this out for the life of me. I have a custom table view cell, in that cell I have a few buttons configured. Each button connects to other view controllers via a storyboard segue. I've recently removed these segues and put a pushViewController method in place. Transition back and forth across the various views works as expected however the destination view controller is not displaying anything! I have some code below as an example.
Buttons have this method set:
[cell.spotButton1 addTarget:self action:#selector(showSpotDetails:) forControlEvents:UIControlEventTouchUpInside];
// etc...
[cell.spotButton4 addTarget:self action:#selector(showSpotDetails:) forControlEvents:UIControlEventTouchUpInside];
// etc...
showSpotDetails Method contains this code:
- (void)showSpotDetails:(id)sender
{
// determine which button (spot) was selected, then use its tag parameter to determine the spot.
UIButton *selectedButton = (UIButton *)sender;
Spot *spot = (Spot *)[spotsArray_ objectAtIndex:selectedButton.tag];
SpotDetails *spotDetails = [[SpotDetails alloc] init];
[spotDetails setSpotDetailsObject:spot];
[self.navigationController pushViewController:spotDetails animated:YES];
}
The details VC does receive the object data.
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"spotDetailsObject %#", spotDetailsObject_.name);
}
The NSLog method below does output the passed object. Also, everything in the details view controller is as it was. Nothing has changed on the details VC. It just does not render anything ever since I removed the segue and added the pushViewController method. Perhaps I am missing something on the pushViewController method? I never really do things this way, I try to always use segues...
Any suggestions?
Welcome to the real world. Previously, the storyboard was a crutch; you were hiding from yourself the true facts about how view controllers work. Now you are trying to throw away that crutch. Good! But now you must learn to walk. :) The key here is this line:
SpotDetails *spotDetails = [[SpotDetails alloc] init];
SpotDetails is a UIViewController subclass. You are not doing anything here that would cause this UIViewController to have a view. Thus you are ending up a with blank generic view! If you want a UIViewController to have a view, you need to give it a view somehow. For example, you could draw the view in a nib called SpotDetails.xib where the File's Owner is an SpotDetails instance. Or you could construct the view's contents in code in your override of viewDidLoad. The details are in the UIViewController documentation, or, even better, read my book which tells you all about how a view controller gets its view:
http://www.apeth.com/iOSBook/ch19.html
The reason this problem didn't arise before is that you drew the view in the same nib as the view controller (i.e. the storyboard file). But when you alloc-init a SpotDetails, that is not the same instance as the one in the storyboard file, so you don't get that view. Thus, one solution could be to load the storyboard and fetch that SpotDetails instance, the one in the storyboard (by calling instantiateViewControllerWithIdentifier:). I explain how to do that here:
http://www.apeth.com/iOSBook/ch19.html#SECsivc

How do I make a reusable XIB with it's own UIViewController?

I am trying to create a reusable "picker". It is basically like a keypad of a phone. Since I will be using this a lot in my iPhone app, I have been frustrated with trying to make it appear.
It is in its own XIB file and has its own UIViewController subclass as the FileOwner.
However, when I instantiate this with:
MonthPickerViewController *mpvc
= [[MonthPickerViewController alloc] initWithNibName:#"MonthPicker"
bundle:nil];
Nothing happens on the screen. Yet is does fire the -viewWillAppear methods, etc.
So, what am I doing wrong either in code or in InterfaceBuilder that is preventing my view to appear?
Are you pushing the view controller?
[[self navigationController] pushViewController:mpvc animated:YES];
Or are you adding the view controller's view as a subView of your current view?
First, make sure you've hooked everything up right inside Interface Builder. An easy gotcha is to forget to connect the View object up to the view outlet of your UIViewController subclass.
Then, as Adam says, you need to actually display the view. Assuming you're doing this inside the code of another view controller, you'd need something like the following if you just wanted the new view to appear ontop of your current view:
[self.view addSubview:mpvc.view];
Of if you are using a navigation controller to stack views:-
[[self navigationController] pushViewController:mpvc animated:YES];