I am using this amazing PopupViewController (https://github.com/martinjuhasz/MJPopupViewController) control. My app uses storyboards.
I have created a custom Segue as per developers instruction(https://github.com/martinjuhasz/MJPopupViewController/issues/8) and changed the UIViewController size property to Freeform and re sized it smaller than full screen. But when it called, it shows full screen.
Code for custom Segue is below
#import "PopupSegue.h"
#import "UIViewController+MJPopupViewController.h"
#implementation PopupSegue
- (void)perform {
[self.sourceViewController presentPopupViewController:self.destinationViewController animationType:MJPopupViewAnimationFade];
}
#end
What I am doing wrong? Also is there any better open source PopupViewController with storyboard support?
I need to uncheck option "Resize View From NIB" in your View Controller's Attributes Inspector
Related
I use a UIScrollView for some of my views to display some long textviews. I'm using XCode 4 and in the Storyboard I have placed the UIScrollView directly onto the ViewController scene.
Now I see in tutorials and stuff that people have a regular View between the view controller and scrollview. Is there a reason for doing that?
I've tried doing the same in my app following this tutorial, but I can't make it work with the storyboard, can't find the connection etc..
It looks like it works fine doing it my way in the simulator, but should I find a way to put a view behind it for some reason? If so, how can I do that properly with the storyboard?
Here's code for how I've done it, + made the connection from the Outlet to the ScrollView in the Storyboard.
InfoViewController.h
#import <UIKit/UIKit.h>
#interface InfoViewController : UIViewController{
IBOutlet UIScrollView *theScroller;
}
#end
InfoViewController.m
#import "InfoViewController.h"
#interface InfoViewController ()
#end
#implementation InfoViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[theScroller setScrollEnabled:YES];
[theScroller setContentSize:CGSizeMake(320,750)];
self.navigationItem.title = #"Title";
}
#end
PS. I can't find a way to scroll down through the scrollview in the storyboard, it doesn't work to just scroll on it with the mouse if thats the way, have my way to set this up maybe disabled this..?
And when thinking about it: If I want the scrollview to be smaller than the View itself, I should put it inside a view in the storyboard, right? So if you know a tutorial on how to do that or if you can describe the procedure, feel free to.
I'm having some problems because I don't know how it can be done. Someone help me please.
Problem:
I have a project with a UIViewController class with created all time when I create a new project in Xcode. In this viewController, I have a xib file for designing in Xcode.
What I need is to create some views and design them in Interface Builder like this:
But I need these views to be UIViewControllers, not UIViews.
The project should look like:
So I don't know how I can do this in IB but I can do it from source code in ViewController.m
tab = [[TabBarController alloc] initWithNibName:#"mytestview" bundle:nil];
[tab.view setFrame:CGRectMake(100, 100, 400, 600)];
[self.view addSubview:tab.view];
But it's not my views it's a different object, and if I want to change position or size I must do it from code. How I can do same things in Interface Builder?
Let's consider following example based on Master-Detailed Application for iPhone only.
So, add new view controller in newly created project in Xcode:
I called it NewInsideViewController. Create it without xib:
Open DetailViewController.xib. Drag View Controller and View(*) objects from library to Objects area like this (I changed view's color to LightGray):
Choose this View Controller and change its Class from UIViewController to NewInsideController at the Identity Inspector:
Assign our View(*) to NewInsideController as a view:
Now all main actions in IB finished. We need to create instance of NewInsideController in our DetailViewController. You can do it by hand, but Xcode has a nice feature - drag-n-drop ;)
I called this property as myNewInsideController and DetailViewController.h looks like this:
#import <UIKit/UIKit.h>
#import "NewInsideController.h"
#interface DetailViewController : UIViewController
#property (strong, nonatomic) id detailItem;
#property (strong, nonatomic) IBOutlet NewInsideController *myNewInsideController;
#property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#end
Well, now our NewInsideController ready to work and manage its view. Let's add button and action to that view in order to verify this:
Write some code in IBAction in NewInsideController.
- (IBAction)insideButtonClick:(id)sender {
float rPart = arc4random()%100/100.0f;
float gPart = arc4random()%100/100.0f;
self.view.backgroundColor = [UIColor colorWithRed:rPart green:gPart blue:0.5f alpha:1.0f];
}
Run program.
If I understand the question clearly:
You have a parent view and controller, coming from a XIB.
You have placed subviews into the parent view.
You're wanting each subview placed into the parent view to have it's own (custom) controller, but you don't know how to add view controller's to your hierarchy (XCode will not let you drag view controllers into a view's canvas).
So, to answer the question succinctly: Let's assume you have a handful of custom UIViewController's in your project (each view controller consisting of a .h and a .m). Remember that you if you are laying these out in the context of the parent, they shouldn't have their own XIBs (you cannot nest XIBs in IB). What is important to note here is that you should only "layout" the interface in one location. If you want to have a XIB for each subview, this is not the correct approach. What you can (not should) do, however, is have several custom viewControllers, each connected to it's own view sitting within your parentView, and you can have the outlets of your sub view controller's set to objects in this parentView. Phew, kinda messy. The other thing you'd need to be aware of is that your parent view controller would need a reference to each of it's sub view controllers in order for you to be able to access those sub-controllers and their outlets programmatically, so for each sub view controller you add, you would also need to add an IBOutlet in your parent view controller pointing to each subviewController:
ParentViewController.h
#property (nonatomic, weak) IBOutlet CustomUIViewController *firstCustomController;
And then for example to set the background color on the view of your first custom subview/controller:
ParentViewController.m
[[[self firstCustomController] view] setBackgroundColor:[UIColor whiteColor]];
Open up your parent view controller in IB. If you look in your drawer of available objects, you'll find a generic UIViewController object. Drag this into your parent view controller (NOT onto it's views canvas, rather into the parent UIViewController object itself as seen in the left-column of IB builder). Select the generic view controller you've added and set it's class to your desired UIViewController subclass. Now, when your XIB loads, it will instantiate an instance of your custom view controller along with whatever you've added to it's canvas.
Finally, drag a generic UIView onto your canvas, placing it inside your existing controller's view (your screenshot already shows this as done). Right-click your custom view controller, and connect it's 'view' outlet to the view you added.
Now when you run, your custom view controller has a view that is on the screen that is the view of your custom controller subclass, and you didn't do any of it in code.
So now that you've done it, consider whether or not it is the best choice: Nested view controllers are messy to build (as you've seen) and aren't necessarily a good design decision: http://blog.carbonfive.com/2011/03/09/abusing-uiviewcontrollers/
Although iOS5 does support nested view controllers, personally I'd avoid using them. I value a best practice dictating one screen = one view controller.
You never, EVER, want to take views which are already under the control of a certain view controller, and make them subviews of another view controller's view.
View Controllers are the C part in the MVC design pattern - They are in charge of controlling a view (and its subviews). You can't take a view which is being managed by a controller, and stick it as a subview of a different controller's view - If you do that, it becomes ambigous who is responsible to manage this view.
Even though this "sticking" might be possible technically, it creates code which is hard to understand, hard to maintain, and most importantly - will cause bugs due to the unclarity of who is responsible to manage the view, and due to the fact that Apple's View/Controller framework doesn't support this.
For example: If the device is low on memory, Apple makes sure to unload views which are not currently displayed. Apple relies on the view controllers hierarchy to know when it can unload views. If you stick the view controller's view in another view controller's view, it's very likely that the view will never be unloaded even if it isn't visible.
Instead of breaking the view controller hierarchy, do one of the following:
Just add subviews to your view normally, either in interface builder, or in -viewDidLoad: to add them programatically, or (rarer) override -loadView.
Use view controller containment, either with Apple's ready-made ones (UINavigationController,UISplitViewController etc.) or with your own container view controllers (iOS>5).
Display view controllers modally.
The bad idea of breaking a view controller hierarchy is indeed very common and often seen in 3rd parties, probably because it's so easy and seemingly straightforward. Unfortunately this causes the aforementioned bugs :-(
I really recommend to everyone participating in this thread and comments to read Apple's View Controller Programming Guide, and watch WWDC 2011 "View Controller Containment" video.
I created a window based application, and I created a separate UITableViewController file called "HomeViewController" which right now only has a basic table.
In the MainWindow.xib file, I put a UIView in the bottom half of the screen, and I wish to put the HomeViewController tableview within this newly added UIView called "conferences".
Any suggestions as to how to push this file?
First off, usually your primary first view originates from a view controller that is loaded by the UIApplication object. The MainWindow nib's owner is UIApplication so you probably don't want to be mucking with the MainWindow nib. Rather, you want to muck with the view of the view controller loaded by MainWindow nib. If you look at the view displayed in IB for MainWindow.nib, it should say which view controller's view it is loading.
So, in IB for the view of view controller being loaded by MainWindow nib, this is where you want to place your UITableView. For purposes of this explanation, I will call this view controller, MucksViewController and associated nib, MucksView.nib.
I think what I would do, then, is drag and drop a UITableView into the view for MucksView.nib. Position it in the bottom half of the screen, as you described. Attach this UITableView to an IBOutlet property in MucksViewController header file. Next, drag and drop a UIViewController object into the main window for MucksView.nib. Make this UIViewController object's owner your HomeViewController class and also attach it to an IBOutlet property of type HomeViewController in MucksViewController's header file.
Now, in MucksViewController's class file, probably in viewDidLoad method, programmatically make the HomeViewController object the data source and delegate of the UITableView object.
But, I'm wondering, do you really need HomeViewController? It would be cleaner just to make MucksViewController the data source and delegate.
I hope this helps and is not too confusing.
Instead of a UITableViewController, use a UIViewController which implements the tableview delegate and datasource. in your MainWindow.xib, add a standard uitableview as a subview to the view where it should be. then also drag a HomeViewController to the xib (which should now be a uiviewcontroller sub class). click on the tableview, open the inspecor, go to connections, and drag the delegate and datasource to the HomeViewController in the xib.
quick question - I have my "first view" which is going to be the ONLY view in my application. I've added a UITabBar to this view using Interface Builder. I am simply wanting to use this as a menu to control the contents of a scroll view.
For example, the user clicks on the first icon in the UITabBar - I get its tag, then based on that, will add a subview to the scrollview. This is working ok....
...but, I have been viewing a few tutorials on tabbars and it seems that 99% of the time they are used to control views. I simply want it to return my tags.
So my question is this: is what I am doing ok?? Can it be used for simply returning a value rather than changing a view? If this is common/OK practice, how on earth do I reference it?
I can get the selected item tag, but cannot actually reference the uiTabBar to make the first button selected. In my .h file, I tried to specify an IBOutlet for the controller, but I cannot link this in IB.
thanks for any info!
To receive notifications that a tab bar item has been clicked you need to modify your view controller to implement the UITabBarDelegate protocol and add an outlet for the tab bar. To do this, modify your declaration in MyViewController.h to something like this:
#interface MyViewController : UIViewController <UITabBarDelegate> {
UITabBar *tabBar;
...
}
#property (nonatomic, assign) IBOutlet UITabBar *tabBar;
Then implement the tabBar:didSelectItem method in MyViewController.m as follows:
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
NSLog(#"Tab clicked: %d", item.tag);
}
You must also set your view controller as the delegate of the tab bar in IB. (hint: connect up the 'delegate' outlet from the tab bar to File's Owner).
To access the tab bar from your view controller use the tabBar property and do things like:
self.tabBar.selectedItem = [self.tabBar.items objectAtIndex:0];
As to whether this is a good idea - why not? All the tutorials show a tab bar being used with a UITabBarContoller to switch views, but it is designed to operate as a stand-alone control as well. As long as you are not breaking any HIG rules then how you implement your interface switching is up to you.
I've got a UITabController. One of the tabs is a UINavigationController. Pushing and popping the navigation stack works just fine. Every UIViewController has his own NIB with just the UIView hooked up. But unfortunately I only get a title displayed for the root navigation controller!
Usually when creating a UIViewController in a NIB you have a title attribute that you can set. But in this case the view controller is the NIB file owner. And in IB there is no way to set the title.
What I can do is to set the title in initWithNib and then it shows up.
if (self = [super initWithNibName: #"MyViewController" bundle:nil]) {
self.title = #"test";
}
But I want to define the title in IB.
I am a bit lost here. Any suggestions?
This is indeed all possible in IB.
You need to load up the NIB file with the UITabController in it. Then, set the View Mode (set of 3 icons at top left) to the middle option. This shows all the components as a nested tree.
Then select the View Controller in question, and bring up the Attributes Inspector. There you will see that you can change the title.
Have included a screenshot so you can see what I mean...
alt text http://img7.imageshack.us/img7/1875/screenshot20090903at120.png
So apparently their is no way to set the title of the UIViewController in this scenario. Too bad.