iOS6 Orientation with NavigationController - ios6

I am developing an application that has several views and a root view controller. It's based on UINavigationController using pushViewController:
In didFinishLaunchingWithOptions:
BIDLoginController *loginController = [[BIDLoginController alloc] initWithNibName:#"Login" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:loginController];
[self.window setRootViewController:self.navController];
In loginController:
BIDMainPageController *mainPageController = [[BIDMainPageController alloc] initWithNibName:#"MainPage" bundle:nil];
[self.navigationController pushViewController:mainPageController animated:YES];
but the view controllers are subclasses of UIViewController, not UINavigationController. Now I want some of the views to support orientation(portrait and landscape) and some of them only support portrait. I have tried the following:
- (BOOL)shouldAutorotate
{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
It doesn't work. shouldAutorotate: method never been called. I have tried UINavigationControllerDelegate with no result either. When I change these view controllers' super class from UIViewController to UINavigationController, the view doesn't show up, only a navigation bar is shown. Can anyone help with this?

You can't do what you are describing. iOS 6 doesn't support forcing different child view controllers of a UINavigationController to rotate. They can respond differently to device rotation, but they cannot be forced to rotate.

Related

Passing data between two containers in a same viewcontroller

I'm new to iOS programming, I read a lot of tutorials and forums but I still can't figure the best way to manage a project.
What I want is the iPad screen to display a CollectionView and a TableView side by side.
Actions in the CollectionView should change TableView content. SplitViewController won't do the job because of the fixed size of the split.
For now I'm using Storyboard, I created a ViewController and added two ContainerViews in it. Each container is linked by an XCode generated segue to a view controller (LeftViewController and RightViewController).
I'm trying to figure the smartest way to manage actions on the LeftViewController and send changes to the RightViewController.
I would like to use Storyboard that seems more elegant, but I'm not sure how to implement this.
Assuming you know the way to establish delegate methods (#protocol, see here for links), the key elements will be grabbing the two viewControllers embedded in containers as they are being loaded, setting the primary viewController as delegate, and sending the messages when something changes. For starters, if communication needs to flow both ways between controllers, set up an instance variable for each VC.
Given VCPrime, CollectionVC, and TableVC:
First, in storyboards, name each of your segues (from the containerViews to the VCs). In VCPrime, implement prepareForSegue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"collection"]) {
self.collectionVC = (CollectionVC *)[segue destinationViewController];
self.collectionVC.delegate = self;
}
if ([segue.identifier isEqualToString:#"table"]) {
self.tableVC = (TableVC *)[segue destinationViewController];
self.tableVC.delegate = self;
}
}
You must also implement the delegate methods in VCPrime, and declare CollectionDelegate, TableDelegate, or however you named them.
In CollectionVC, when someone selects something (or whatever), check that the delegate responds to your delegate method, then send that message:
if ([self.delegate respondsToSelector:#selector(doSomething)]) [self.delegate doSomething];
Then alter TableVC in the method that is called.
This is just a quick rundown. The internets are alive with great code examples.
I think I might have an improvement in Swift (the answer is old but I was facing this problem a day ago). I re-implemented the above in Swift, but with a twist. Instead of setting the VCPrime as a delegate for for both CollectionVC and TableVC, I would make the TableVC a delegate of CollectionVC. That is because CollectionVC needs to control TableVC. In general we can call a "master VC" the one that controls and the "delegate VC" the one that is controlled. In order to make sure that both VC are actually instantiated when I set one as the delegate of the other, I use Swift optionals and optional bindings. Here is a sample of code" (note that the master needs to have a "delegate" property and you might want to declare the appropriate protocols):
import UIKit
class ContainerController: UIViewController {
private var masterViewController: myMasterViewController?
private var delegateViewController: myDelegateViewController?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "myMasterViewController" {
masterViewController = segue.destinationViewController as? myMasterViewController
} else if segue.identifier == "myDelegateViewController" {
delegateViewController = segue.destinationViewController as? myDelegateViewController
}
if let master = masterViewController, delegate = delegateViewController {
println("Master and delegate set")
master.delegate = delegate
}
}
}

Do XAML objects remain virtually present when leaving a XAML page in Windows 8 App?

I use the MVVM Light Toolkit to define the association between the view-model and the view.
The container is instructed to register a view-model as a singleton instance. Thus, the same instance will always be returned when the GagaViewModel is required:
public GagaViewModel GagaViewModel
{
get
{
var vm = ServiceLocator.Current.GetInstance<GagaViewModel>();
vm.Setup(); //Clear the ObservableCollection
return vm;
}
}
You can click on a thumbnail item on PriorGaga.xml. The self-chosen item is then selected in the GridView "MyGridView" in Gaga.xaml. Code-behind file of Gaga.xaml:
protected override async void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
var itemId = navigationParameter as String;
if (String.IsNullOrEmpty(itemId))
{
throw new ArgumentException("navigationParameter was either null or empty");
}
await ((GagaViewModel)DataContext).Init(itemId); //Busy(-Indicator) while loading data from server, filling the ObservableCollection and writing the selected item down
BringItemIntoView();
}
private void BringItemIntoView()
{
var vm = (GagaViewModel)DataContext;
Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() => MyGridView.ScrollIntoView(vm.SelectedItem));
}
That works fine. As a sample: Item #45 appears within the viewport immediately (correct viewport position from the beginning).
But when you click the back button and return to Gaga.xaml by selecting an arbitrarily thumbnail item (let's just say #29), you will see item #1 and then the switch to #29 (the viewport is moving over the container). Do someone know what's going on under there? Are there any virtualized items in the container from the preceding Gaga.xaml visit?
My understanding is that the lifespan of the instance of your Gaga page is determined by its NavigationCacheMode property. By default, it is set to Disabled. Assuming that you haven't changed this property, you should be seeing a new instance of your Gaga page every time you navigate to it. You can verify this behavior by setting a breakpoint in its constructor. Consequently, I would think that each time you navigate to Gaga, the behavior of the UI should be identical, because everything is fresh.
(I wanted to add this as a comment, since I haven't actually answered your question, but sadly I do not have enough rep. I apologize in advance; please do not smite me down!)

Subclassing UICollectionReusableView

I've been trying to subclass UICollectionReusableView in a non-storyboard iPad project. I've built a view in IB and hooked it up to my custom class, registered the class for reuse in the viewController where my collection view lives, and am calling it correctly in
UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
However, nothing shows up in my header areas in the UICollectionView. I think I need too init the view with coder, but am unsure how to do that correctly. I followed a couple of examples I found, but the header view still does not appear in my collection view.
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[[NSBundle mainBundle] loadNibNamed:#"CVHeaderView" owner:self options:nil];
[self addSubview:self.categoryNameLabel];
}
return self;
}
Can anyone point me in the right direction?
If you use a storyboard and select the header/footer checkmark initWithCoder: will be called.
If you do not use the storyboard (or do not click header/footer) but hook it up manually you have to register your custom classes and initWithFrame: will be called.
[self.collectionView registerClass:[GameCardCell class] forCellWithReuseIdentifier:#"GameCardCell"];
[self.collectionView registerClass:[PlayerHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"PlayerHeaderView"];
[self.collectionView registerClass:[PlayerFooterView class] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:#"PlayerFooterView"];
Note: Both will be called only once. If the view comes out of the cache prepareForReuse will be called.
In my case, initWithFrame: is called automatically when dequeueing it for the first time. Try to implement this method and see if it works.

Hide MasterViewController in Master-Detail Application using Storyboard (XCode 4.2)

I have created new application using Master-Detail Templte with storyboard. I want to give user facility where they can Hide/Show Master View Controller in Landscape mode. I found few examples on net but none are using story board and Master-Detail template with Navigation Controller.
I have already implemented splitviewcontroller willHideViewController & willShowViewController which help me hide Master View Controller in Portrait mode. I am using below code in didFinishLaunchingWithOptions method of App Delegate to load views intially,
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
I would appriciate if you can point me right direction.
Thanks,
Tapan Desai
The master view is presented in a popover and the popover can be used to control the visibility of the master.
So...follow these steps:
1) Create a property to hold the popoverController
#property (nonatomic, strong) UIPopoverController *pc;
2) Capture the popoverController on the SplitViewController willHide delegate call
-(void) splitViewController:(UISplitViewController *)svc
willHideViewController:(UIViewController *)aViewController
withBarButtonItem:(UIBarButtonItem *)barButtonItem
forPopoverController:(UIPopoverController *)pc
{
barButtonItem.title = #"Menu";
id detailViewController = [self.splitViewController.viewControllers lastObject];
[detailViewController setSplitViewBarButtonItem:barButtonItem];
self.pc = pc; //poppver controller
}
3) Finally just use the pc var to dismiss the popover
if (self.pc) {
[self.pc dismissPopoverAnimated:YES];
}

Declaring an array of UIImageViews globally in Xcode

I created an array of ImageViews in a Buttonclicked method:
UIImageView *arrayOfImageViews[10]
I successfully loaded them on the screen using a loop. (Big accomplishment for this beginner!)
But I want to refer to them in other methods (e.g. touchMove).
Where do I declare arrayOfImageViews to be both an array and a class of UIImageView so that I can use them in other methods? From what I can find, I'm to declare them in the .h and above Implementation in the .m. But I can't figure out the code and location to define the object as an array of UIImageViews in anything but the original function.
Try using a property. So in the .h file, you want to define the property something like this:
#interface MyClass: UIView {
NSArray *arrayOfImageViews;
}
#property (nonatomic,retain) NSArray *arrayOfImageViews;
Now in the implementation (.m file) You need to bind this property like this
#implementation MyClass
#synthesize arrayOfImageViews;
//now you need to initialize the array of images like this (look for the method viewDidLoad or //just add it)
- (void)viewDidLoad
{
NSMutableArray *tmpImages = [[NSMutableArray alloc]init];
//initialize images here
[self setArrayOfImageViews:tmpImages];
[tmpImages release];
[super viewDidLoad];
}
That should do it... Sorry I didn't have time to post code that actually compiles but it should help. Basically now you have a property on the class and you can access it like self.arrayOfImages, or even just arrayOfImages (from within MyClass). Also, I used NSArray which I suggest you do too. However you can also use UIImageView* arrayOfImages if you prefer.

Resources