I have a tab controller and within this tab controller one of the views is called random. Within random, I have added multiple views (without making new .xib files or .m/.h) that I simply create in interface builder and linkup. For example, I created landscape view. I have a button within the original view (random) that takes me to landscape view with a simple line of code: self.view=landscape;. This works. My problem is having a custom "back" button that will take me to the original view. I tried calling self.view=view;
but this did not work. When I check the connection in interface builder with the original view, it simple just says "view". What line of code is needed to return me to the original view ("view")?
Thank you in advance and my apology if this is extremely obvious
I guess you could persist your original view so that you can restore it later. This should do it:
Add this property to your view controller (in your .h header file):
#property (nonatomic, retain) IBOutlet UIView *originalView;
Autogenerate the accessors (in your .m implementation file):
#synthetize originalView
Inside your viewDidLoad method, assign the actual original view from the NIB to it:
self.originalView = self.view
And then to return to your original view after a click on your back button, do this:
self.view = self.originalView
Related
I have created a UIPickerView in a view controller called ActivityLevelPickerViewController. I want to get this picker view to display in a view controller called RegisterViewController.
How do I call the picker view in RegisterViewContrller?
There are two options. One is to just copy over all the code related to the pickerView from ActivityLevelPickerViewController to your RegisterViewController. The other option is to create a new UIPickerView subclass and move all the code related to populating the rows there. The nice thing about creating a subclass is that if you want to make a change to your picker, you can just change it once rather than in every view controller. The property declaration would look something like this:
#property (weak, nonatomic) IBOutlet MyPickerViewSubclass *pickerView;
Don't forget to import your picker view subclass in your view controller if you go with the subclassing option.
I have a TableViewController With a dynamic cell and a view I added above it.
I've created a UIView class and added it as a custom class for that view ( just like I do with a custom cell) but I can't drag labels etc from that UIView to its .h file. Only to the main TableViewController.h file. Any idea what's the problem?
A table view in a UITableViewController takes up the whole screen, so the view you added is actually in the table view, not above it, so that's why you can connect to the table view controller. If you want to add a view above the table, use a UIViewController instead, and resize the table view so it doesn't take up the whole screen.
I've noticed this too (for an OS X project) in Interface Builder. I'm not sure if it is a bug or not in IB.
What you will have to do is enter the #property declarations in your .h file manually and then you will be able to connect them.
I've made a view in my storyboard which I've now decided I'd rather display its data via static table cells.
I can't use static table views in a UIViewController (Static table views are only valid when embedded in UITableViewController instances). So, I need to convert my existing UIViewController to a UITableViewController somehow. I've changed the .h file's parent, but that hasn't done it.
Is there another way to get this going? I'd really rather not have to make a new VC in the storyboard and move everything over, it's a big hassle.
I'll add to this, since the question is about how to change a UIViewController into a UITableViewController, and given that this question is over a year old and the original answer, while valid and may or may not have been the only solution at the time, doesn't actually answer the question and is not the only solution.
It IS possible to do this, you just have to set up the table view delegate and datasource outlets in IB, and manually edit the storyboard XML, which sounds scary but is actually very easy.
First, change your class's parent to be a UITableViewController. UITableViewController already adopts the UITableViewDatasource and UITableViewDelegate protocols, so if your class does too you can remove them:
#implementation MyTableViewController : UITableViewController
...
#end
Next, create new referencing outlets on your UITableView for its dataSource and delegate. The easiest way to do this is to control-drag from the UITableView to itself. The popup will give you the dataSource and delegate options.
Lastly, you need to change the storyboard XML. The storyboard file can get pretty big pretty fast. The easiest way to find the scene you are looking for is by setting Storyboard Identifier in the Identity Inspector. To view the XML directly, right click on the storyboard file in the project navigator and select "Open As -> Source Code". Now just search for whatever you set the reuse identifier to earlier. You'll see something similar to this:
<!-- My Table View Controller -->
<scene sceneID="EuE-XX-cCb">
<objects>
<viewController storyboardIdentifier="MY_TABLE_VIEW_IDENTIFIER" ... >
// Lots of other stuff
</viewController>
</objects>
</scene>
All you need to do is change the opening and closing view controller tags
<viewController>
</viewController>
to be tableViewController instead
<tableViewController>
</tableViewController>
That's it! No need to create a new UITableViewController scene or embed a UITableViewController in a container view.
EDIT:
I should also add that the UITableView MUST be the root view. It cannot be embedded inside another UIView.
If you want your static cell table view not to take up the entire screen, then using a container view is the easiest way to go. Start with a regular UIViewController and drag a container view (next to normal UIView in the object list) into its view. Resize it however you want -- the storyboard will automatically provide a view controller connected to this container view with an embed segue. Delete that controller, drag out a table view controller and right-drag from the container view to this table view controller to make a new embed segue. This table view controller can be accessed from the UIViewController with its childViewControllers property (and conversely, you can access the UIViewController from the table view controller with parentViewController if you need to).
What I did, is creating a UITableViewController in IB, open the Storyboard with a text editor, and copy all the nodes inside from the UIViewController to the UITableViewController.
I think that with this way there's less risk of deleting something important.
Before copying the sections objects, make sure that both tableviews (UIViewController and UITableViewController) have the same properties set like: static or dynamic cells, style (plain or grouped), etc.
I so far only have the interface builder layout
I'm not clear on the syntax to reference all of these items from the layout
I know that IBOutlet has to be used somewhere, but I need a bit more handholding on what this objective C is doing. Nothing I've read tells me exactly why some declarations start with + and others with -
What I want to do is click a button in my layout, have a modal view pop up and change the background on the entire layout.
so the first step is referencing all these items I've made in the nib. help? (or post a link to more intuitive tutorials that you know about)
So you probably want to create an IBOutlet for your background view. Maybe it's a UIImageView that you can set it's image property based on what the user selects in the modal view. For this you would just declare the UIImageView you have in your IB file
UIImageView *imageView;
and then declare it as a property
#property (nonatomic,retain)IBOutlet UIImageView *imageView;
and synthesize it in your .m file
#synthesize imageView;
Don't forget to release it if you're not using ARC.
Then you can open up interface builder and if you click on your view controller File's Owner and go to the connections inspector you will see there is a new connection there for imageView. Just drag that connection over to your UIImageView in the IB file and that's it. You now have a reference in your code that connects to your UIImageView in IB.
That will allow you to set the UIImageView in your code by typing something like
self.imageView.image = [UIImage imageNamed:theNameTheUserJustPicked];
In order to get the modal view, you need an IBAction to trigger a method in your code so declare one like this in your .h file of your main nib.
- (IBAction)displayViewBackgroundChooser;
and then define it in your .m file.
- (IBAction)displayViewBackgroundChooser {
//present your new view on screen here
}
Then go back to interface builder and click on the File's Owner again. You should see it there in the connections inspector and then you can connect it to a button, for example, that would trigger that method.
Hope this helps to clear things up a bit on IBOutlets and IBActions.
You can make your UI elements created in IB interact with your code by means of IBOutlets and IBActions.
In your case, I would associate an action to the button, so that it is fired when the button is clicked; the action would open a modal view, and you could change the background of that view in the viewDidLoad method of the associated controller.
Here you find a video tutorial about adding an outlet. And here, the same about actions.
About your doubt on + and -, - identifies a normal method defined in a class; + defines a class method, i.e., a method that you can call on the class directly, without having to instantiate it first. Have a look at this S.O. article for more.
I've created a ChildViewController class, and then a nib that uses that class.
Then I created a BaseView, that includes some buttons, and some text that I'll be changing programmatically.
Then I created two more views (Boy and Girl), that I want to be able to lay behind the baseview so that the background color is different along with some graphics in an ImageView. I've named the views that I created in IB 'Boy' and 'Girl'...
But when I go back to my code where I'm calling ChildViewController, I'm not sure how to access the views I created so I can call insertSubView. Do I need to instantiate them in code? (in ViewDidLoad perhaps?) Does the nib create the instances when it loads?
I'm confused about how to handle multiple views for a single ViewController
edit =================
#Pablo Santa Cruz
Your answer assumes that i have two nibs and two view controllers (one for each view). I want to know if I can use one nib and one controller, and load in UIViews. It seems silly to create another nib and controller, when all want to do is change the background color and some graphics. Can't I programatically load in UIViews into a UIViewController?
Add IBOutlets in your App Controller class in Xcode then link them in IB (ctrl-click or right-click) from the connections tab in the Inspector to the object.
Then you will be able to send method calls to the objects.
The code in Xcode should look like this:
#interface AppController : NSObject
{
IBOutlet Girl girlIvarName1;
IBOutlet Boy boyIvarName2;
}
#end
You can access a UIView programatically by assigning a value to its tag property, which can be set in IB on the first tab of the inspector (Command 1)
The tag value defaults to zero, so if you want to access it specifically, make it non zero and unique. e.g. 100, which I will use in the example code below
Once the tag is set you can access the view using the following code in your UIViewController that was initWithNibName for the NIB containing the tagged view
UIView *aView = [self.view viewWithTag:100];
You can get instances for your IBuilder views with this piece of code:
boyViewController = [[BoyViewController alloc] initWithNibName:#"BoyViewController" bundle:nil];
girlViewController = [[GirlViewController alloc] initWithNibName:#"GirlViewController" bundle:nil];
Assuming your NIB file names are BoyViewController and GirlViewController. With those instances, you can do whatever you need to. I.E., adding them to a parent view (with addSubView message on the parent).