Using default tab-controller created project... first view controller doesn't respond to addsubview - iphone

I created a project using the default tab-controller project. I am using interface builder to edit the .xib file and add images and buttons. I hook them up to the FirstViewController object in interface builder (that I created and set it's class to the same as the code file). I hooked everything up using IBoutlets and IBActions.
Everything was working fine, but then I made some changes in interface builder (added a UILabel) and now a method that is run when clicked (I ran through it with the debugger) has a line that adds a subview to the view controller, and it acts as if it wasn't executed. The method (and code is run through) is executed with no errors (per the debugger) but the view is simply not being added. This happened after I made some change via interface builder.
Now, if I hook-up my button to "Selected First View Controller" by clicking on the appropriate tab and dragging the IBOutlet to the UILabel, that label now has multiple referencing outlets. Now, if I do the same thing for the button, the method (the IBAction) is executed twice but the subview is actually added and displayed. But, I get a memory access error because my IBAction (button) method access a property that stores something. I am guessing this has to do with somehow creating the memory in the First View Controller but trying to access it in the Selected First View Controller? If that makes any sense?
I have no idea why this is happening and why it just the button suddenly stopped working. I tried to explain this problem the best I could, it is sort of confusing. But if anyone has any tips or ideas I would love to hear what you guys think about this problem and how to solve it.

Are you sure the first outlet is actually hooked up. If you name an outlet such that it conflicts with some other property that is set while the nib is loading (via initWithCoder:) it can cause things to not end up being hooked up properly. You can check that by NSLog'ing out the value of the outlets in your awakeFromNib.

It also sounds - and feel free to correct me if I'm mistaken - that you're attaching actions in the view loaded by the tab bar to the tab bar's controller. The two entities are quite different and any data that you wish to access from the view should be referenced from the view's controller rather than the tab bar's controller (which should have a fairly light-weight job in loading and unloading your other view controllers). Similarly, you should not be adding a subview to the view controller, it has no idea about what to do with a subview - you should be using the view controller to add a subview to your view. While it seems like a matter of semantics a view controller is fundamentally different from a view. The former has the job of managing the contents and behaviors of a view and to respond to the view's actions where necessarily while the latter is simply a mechanism for displaying thing son the screen.

Related

Can't create outlet using Interface Builder - Lock symbol shown

I'm trying to create outlets using the Interface Builder, however when drag the UILabel from the IB to my controller's .h file the big lock symbol flashes for a few seconds and it doesn't actually create the bind between the UILabel and the outlet (although the code is generated). I also noticed an empty circle is created by this new definition. When it worked, a filled in circle was created on the side).
I've checked the UILabel and all parent views and have checked that their "Lock" property is set to "Inherit (Nothing)" (and have even set them all to "Nothing").
In the IB the UILabel doesn't show the "x" that appear when a UILabel is locked either.
So I have no idea if I'm missing to unlock something, or what I'm doing wrong to be able to create this outlet.
I don't know if this is relevant, but I'm using a custom view controller, and I'm using this same view controller subclass for 2 different view controllers in the same storyboard. I had no problems creating outlets this way for the first view controller.
Tryed reopening XCode (using 4.4.1) with no luck.
Any help is appreciated!
So are you dragging both UILabels from each View Controller into the same file? I don't think that this is possible, on the second view controller, try to Ctrl drag to the file owner within the IB view, that is, assuming that both views are connected to the same instance.
Also, in your identity tab in storyboard, under Localization Locked, make sure your storyboard locked setting is set to default as mentioned in https://stackoverflow.com/a/11169636/720175
I tried adding a totally new scene and would also get the lock symbol. So it wasn't only the scenes, but the whole storyboard. So a quick search on SO lead me to the answer:
https://stackoverflow.com/a/11169636/720175

How can I change Table View Controller's type to a regular View Controller?

I followed the "Storyboard tutorial" and made some Table View Controllers; now I want to change one of them to a regular View Controller.
Is there a way to do that without making a new one?
One option is to edit the storyboard file directly. Navigate to the Storyboard in Finder and open with any text editor. Find the view controller in question and change the node in the xml from tableViewController to viewController.
This saves the pain of having to recreate the view controller, which comes in handy when you have a lot of connections made. This also works the other way around. If you have a viewController that started out as a plain view controller but you want to turn it into a table view controller you can simply edit the file reversing the node.
You need to create a new view controller and drag a tableview into it. Remember to set the delegate and datasource of the tableview to the view controller.
I have had the same scenario where I needed to change the Tableviewcontroller to a view controller. I googled for a work around but ended up without an exact solution. What I did was added a subclass of view controller and dropped a UITableview and added some more controls that I wanted. Pretty inconvenient but worked the way eventually!

Cannot get button to call controller code iPhone 4

My View has a button, myButton, in my XIB. In the XIB the File's Owner is of class HelloWorldViewController. And the view for File's Owner is my View in the XIB.
In the HelloWorldViewController(which resides in MainWindow.XIB) I have - (IBAction) doMyButton:(id)sender and I have the corresponding definition in the HelloWorldViewController.h file.
For my View I have Events (again in the XIB) Touch Up Inside --> File's Owner doMyButton.
For File's Owner I have Received Actions doMyButton --> Rounded Rect Button Touch Up Inside.
I have a debug point on the first line of code that is inside the 'doMyButton' method. When I touch the button (with my mouse in the simulator) I do not hit my break point.
WTF?
Screen Captures of IB if it helps:
Overview
Properties Of Button
If every thing is fine then you are not setting the break point i.e. you are running your code using cmd+R use cmd+y or cmd+enter. cmd+r will run without considering your break points.
Do any of your IBOutlet items function?
If they don't (and since you renamed your XIB file), be sure the File's Owner has the correct custom class set in the interface builder. Otherwise it could be calling the wrong class which could be why your break point isn't firing.
Note: This is unlikely as such an issue should cause a build problem, but I've seen stranger things happen.
Thanks to a co-worker I found out what the problem was. The view I had with the button was in my HelloWorldViewController.xib as it is supposed to be. However, I had drug that view into the Main.xib to be the primary view for the NavController I had setup. I was editing the view in the HelloWorldViewController.xib when I should have been editing (read: making the connections) in the Main.xib where the view was duplicated for the NavController.
I assumed that NavController was simply pointing to the other XIB where my original view was defined, not running off a copy of it. Kind of messed up for a newb perspective.

How to tell if view has appeared via popping or not?

Using a UINavigationViewController, how do I find out how a view has appeared?
The view has either appeared in a straightforward manner, as the first view in the UINavigationController stack. Or it has appeared because a second view has been popped and the first view has revealed itself again. How do you find out which of these happened?
The only reliable way to do this, as far as I'm aware, is to subclass UINavigationController and override the UINavigationBarDelegate methods:
– navigationBar:shouldPushItem:
– navigationBar:didPushItem:
– navigationBar:shouldPopItem:
– navigationBar:didPopItem:
Don't forget to call super, of course.
Simple approach is to add a property to your RootViewController to track whether or not it has pushed another view onto the navigationController.
-(BOOL)hasPushedSecondView;
Initialize to NO in your init method.
Before pushing secondViewControllers view onto the stack, update the property to YES.
In viewWillAppear, check the value and update your view accordingly. Depending on how you want the application to behave you may need to reset the hasPushedsecondview property back to NO.
you could take a look at the leftBarButtonItem or backBarButtonItem, based on how your application is written and determine how the view appeared. If it is on top, unless you have a custom leftBarButtonItem, there would be no object there.
You can determine this directly via a couple of methods on your UIViewController subclass.
From Apple's documentation:
Occasionally, it can be useful to know why a view is appearing or
disappearing. For example, you might want to know whether a view
appeared because it was just added to a container or whether it
appeared because some other content that obscured it was removed. This
particular example often appears when using navigation controllers;
your content controller’s view may appear because the view controller
was just pushed onto the navigation stack or it might appear because
controllers previously above it were popped from the stack.
The UIViewController class provides methods your view controller can
call to determine why the appearance change occurred.
isMovingFromParentViewController: view was hidden because view controller was removed from container
isMovingToParentViewController: view is shown because it's being added to a container
isBeingPresented: view is being shown because it was presented by another view controller
isBeingDismissed: view is being hidden because it was just dimissed

set view property in a UIViewController from a NIB programmatically (not during initialization)

At the beginning of my app, I am initializing a UIViewController with a NIB.
At some point, I am removing the view from the screen, then releasing it, so it no longer takes up memory. (At this point I am also saving the state of the view in the UIViewController)
At a later point, I want to recreate the view and bring it back on screen. I will then restore its state. (Using the same UIViewController, not a new one, since it saved the state)
My question, is when I recreate the view, how do I do so from the NIB, or is this not possible?
To me, the obvious remedies are:
Don't save state in the UIViewcontroller (Where does convention dictate that I do save state?)
Don't release the view (maybe just release all of its subviews?)
Don't load my view from a NIB, create programmatically (seems to go against using IB for everything)
Note:
I am not using a UINavigationController, I am handling the swapping of the views myself, since thee are only 2 of them.
If you need that level of control, you dont really want to use IB. Because, as you noted, if remove the view and then later recreate it, you would have to do it in code then anyway. Just design most of the views in IB, then write some code that generates just this view. Then you can call that same method again later to recreate that view when you need it.
You may be able to archive it and later turn it back into an object, but that seems like an inelgant solution. IB does not allow for dynamic creation of controls at runtime, even if they used to exist but don't anymore. There is no shame in leaving IB out of loop for this. In fact it's probably a good idea.
OR
If its a complicated view with a lot of pieces, put the view in it's own nib, and make a view controller for it. Then you can simply instatiate the view controller with the nib name, and add the controllers view as a subview to you main view. Then your view controller handles loading of the nib, and you get to design it in IB. Nothing says the view of a view controller has to take up the entire screen either.
self.otherController = [[OtherController alloc] initWithNibName:#"Other" bundle:nil];
[self.view addSubview:otherController.view];
Don't create the view controller and the view in the same nib file; either create the controller in code or put the view in a separate nib file. If you later nil out your controller's view property, the controller should recreate the view.
But why are you so worried about this? There's already a mechanism to automatically free up the view if you're low on memory: the low memory warning. It will only destroy and recreate the view if you actually need to do so, and it's built in to the system so you don't have to do anything. Remember the saying about premature optimization?