Can't understand iPhone view layout - iphone

I have an iphone app that I built based off a tutorial (for a different framework so I had to modify things a bit) that uses a TabBar and a NavigationBar on the same View that also contains a UITable populated from an SQLite db.
I built it last night and when you select an item in the UITable it was redirecting to a view that displayed the detail of my item (at that point, just a city name). I went in and tried to modify that DetailView...and nothing I change works.
So I have a few questions/problems:
1) Why is it that my CityDetailView.xib looks like this in Interface Builder:
alt text http://www.jamespwright.com/images/public/detailviewinterfacebuilder.jpg
But looks like this when the app is run:
alt text http://www.jamespwright.com/images/public/wrongdetailview.jpg
I am new to iPhone development, so I'm not even sure where to begin looking for this problem.
I know that the TableViewController is set to CitiesTableViewController and within that controller code in my didSelectRowAtIndexPath I run this code:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
City *city = (City *)[appDelegate.cities objectAtIndex:indexPath.row];
// Initialize a new CityDetailView if there isn't one already
if (self.cityView == nil) {
CityDetailViewController *viewController = [[CityDetailViewController alloc] initWithNibName:#"CityDetailViewController" bundle:[NSBundle mainBundle]];
self.cityView = viewController;
[viewController release];
}
[appDelegate.citiesNavController pushViewController:cityView animated:YES];
self.cityView.city = city;
self.cityView.title = city.name;
[self.cityView.cityName setText:city.name];
[self.cityView.stateName setText:city.state];
[self.cityView.population setText:city.population];
And I have the labels linked up in Interface Builder to the properties in the Controller.
I also have the CityDetailView.xib class identity set to CityDetailViewController which has all the properties correctly declared.
One thing I can't figure out, if I rename CityDetailView.xib to "CityDetailView.xib1" the program still runs the same, but if I change [self.cityView.title = city.name]; to [self.cityView.title = #"Bob's Your Uncle!"]; it displays that change within the program.
On a completely unrelated note, on my TableView (my 2nd tab) I have this odd bar at the bottom that I don't know what it is or how to get rid of it, I'm pretty sure it has to do with the NavigationController but I don't know why or how it's there. It is this one:
alt text http://www.jamespwright.com/images/public/tabandnavigationview.jpg
Can anyone offer me any advice on these problems?

When "nothing happens" when you change source files, there are usually only a few things you're doing:
Dates are screwed up somewhere and you need to clean (Build → Clean)
You're editing the wrong file
You're building the wrong target
No, seriously, you're editing the wrong file, or building the wrong target
Cleaning is definitely the first thing to try. Especially if you can rename the XIB and everything still cheerfully goes on.

The simplest explanation is that self.cityView.stateName and the subsequent labels are not hooked up in interface builder. The controller must have a hooked up outlet to each label in order to populate it. Objective-C won't raise an error if you send a message to an object it can't find.

Related

Switching view controllers without navigation controller

I'm sure this has been asked countless times, and I've seen similar questions though the answer still eludes me.
I have an application with multiple view controllers and as a good view controller does its own task. However I find myself stuck in that I can't switch from one view controller to another. I've seen many people say "use a navigation controller" but this isn't what I want to use due to the unwanted view elements that are part and parcel to view controller.
I've done the following and have had limited success. The view controller is switched but the view does not load and I get an empty view instead:
- (IBAction)showLogin:(id)sender
{
PPLoginViewController *login = [[PPLoginViewController alloc] initWithNibName:#"PPLoginViewController" bundle:nil];
PPAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
appDelegate.window.rootViewController = login;
[self.view insertSubview:login.view atIndex:0];
}
Using UINavigationController as a rootViewController is a good tone of creating iOS application.
As i understand unwanted view elements is a navigationBar? You can just hide it manually, setting:
[self.navigationController setNavigationBarHidden:YES];
And about your case, if you want to change you current viewController(targeting iOS 6), you can just present new one:
[self presentViewController:login animated:YES completion:nil];
or add child (Here is nice example to add and remove a child):
[self addChildViewController:login];
Why to set UINavigationController as a root?
1) First of all it makes your application visible viewcontrollers to be well structured. (Especially it is needed on iPhone). You can always get the stack and pop (or move) to any viewController you want.
2) Why I make always make navigation as a root one, because it makes the application more supportable, so to it will cost not so many code changes to add some features to the app.
If you create one (root) viewcontroller with a lot of children, or which presents other viewcontrolls, it will make your code really difficult to support, and make something like gode-object.
Listen to George, UINavigationController is the way to go. Your reasons for not wanting to use it are not valid.
However, the reason your code doesn't work might have to do with the unnecessary line after setting the rootViewController to the login vc.
Per Apple's documentation, setting rootViewController automatically sets the window's view to the view controller's view.

Linking One View To Another Via A Button

I'm a bit new to programming for iOS, and I'm having some trouble linking one view to another via a button. I'm just creating a simple little app that does some calculations on a NSDate in an attempt to learn XCode and iOS programming.
I've already searched this quite a bit, and I've tried to learn from other examples but I'm having trouble getting the view to present, nothing happens when I press my button (which I've already checked to be linked to the button).
I've been having trouble understanding view programming, so please bear with me.
Here's my code for my button:
-(IBAction)resultsPressed
{
TimeResults *timeResults;
timeResults = [[TimeResults alloc] initWithNibName:#"TimeResults" bundle:nil];
[self.navigationController pushViewController:timeResults animated:YES];
[timeResults release];
}
TimeResults.xib is using a Navigation Controller if it matters, while my root view is simply a view. My thinking behind this was so that I could get the "back" button (though I'm not sure if this is the correct way tot do this, since they are not a part of the same hierarchy). Any suggestions on how this should be done would be greatly appreciated!
Nothing seems wrong with the code you posted, but you should have the Navigation Controller associated with the first nib, as the back button will display by default when a new view is pushed onto the stack.
Also, make sure that the Navigation Controller is set up properly in your AppDelegate. The proper way to do this can be seen if you start a new project and select "Navigation-based Application". If you use the new project as a sample to show you how to set up your old project correctly, you will have to make sure that the nib is set up correctly too. I would suggest using the new project, hooking it up as a UIViewController instead of a UITableViewController, and then moving your code from your old project to this new one.
Finally, make sure that you always import the .h file of the UIViewController you are going to push to. Hope that helps!
To load another view, try
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
TimeResults *timeResults = [[TimeResults alloc] initWithNibName:#"TimeResults" bundle:nil];
[delegate.window setRootViewController:timeResults];
Hope it works. :)

Going back to list in Drill-Down Navigation Based Application using Core Data on iPhone

I want to build a simple drill down app (similar to the Contacts app on the iPhone). I am using Xcode 4.0.
I start by making a new "Navigation Based Application", and also say that I will be using Core Data for storage. I then go and add 'New File' and select UIViewController, and a subclass of UIViewController.
In my RootViewControler (which was made in the template) at didSelectRowAtIndexPath, I do the following:
NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
TrackerDetailViewController *trackerView = [[TrackerDetailViewController alloc] initWithNibName:#"TrackerDetailViewController" bundle:nil];
trackerView.title = [managedObject valueForKey:#"trackerName"];
trackerView.referringObject = managedObject;
[self.navigationController pushViewController:trackerView animated:YES];
[trackerView release];
And this works - I can load up some details in TrackerDetailViewController.
What I cant seem to figure out is how to go back! Most places I am reading online say that this should be happening automatically. I can't seem to get that to happen. If I download a few samples and compile them, they do have a back button - but I dont see how it was added or managed, and can't find what I am missing to not have it.
Check if [managedObject valueForKey:#"trackerName"] is actually returning anything. If not, then there's no title, and no back button will be created.
Oops, just re-read your code. It's the parent that needs a title assigned. Add something like self.title = #"myName; and myName should then appear as your back button in trackerView.

xCode - Changing views between 2 existing xib-files

I'm very new to xCode and objective-C so I wanted to make a simple textRPG.
I'm currently making a character creation process consisting of 4 xib-files. The only way I got switching views to work was to look at the utility-template. Problem is, now I have the first screen being the delegate for the second screen, being the delegate for the third screen etc. So by the end of the character creation process I can't dismiss the views because that just "steps back" through the views.
When I've searched around for a solution I've found a addSubview-method but it seems like that makes a new view, like, empty to arrange programmatically.
All I need is a simple way to switch from one loaded xib to another xib. Have I misunderstood addSubview or do I need something completely different?
(If it helps: I've worked with VB for several years, in case you notice that I missed some kind of concept concerning views and such)
Thanks in advance! :)
Use this code. It is really simple and works well.
View *view = [[View alloc] initWithNibName:#"xibNameGoesHere" bundle:nil];
view.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:view animated:YES completion:nil];
This will switch to another xib file and the two views won't own one another. I am using it in my own game right now.
#Joakim Ok, this is the way I do it. I have a class called RootViewController : UIViewContoller, whose view I add directly to the window. Then I make a subclass of UIView i.e. MyView. All of my views then subclass MyView. I also make an enum for all my views. In RootViewController you should have a switchView:(int)view method that looks something like this:
-(void) switchView:(myView) view
{
[_currentView removeFromSuperview];
switch(view)
{
case titleView:
_currentView = [[TitleView alloc] initWithRoot:self];
break;
case homeView:
_currentView = [[HomeView alloc] initWithRoot:self];
break;
default: break;
}
[self.view addSubview:_currentView];
[_currentView release];
}
in #interface RootViewContoller define MyView *_currentView;
TitleView and HomeView both subclass MyView and have a common method -(id)initWithRoot:(RootViewController*) rvc.
To switch between views use [_rvc switchView:homeView];
Hope this helps :)
It is called UINavigationController. Idea is
1) You push corresponding 'next' controller into navigation controller each time user submits current screen. Bonus - you'll get 'back' button for free on each step of character creation.
2) After character is created you pop all character creation controllers from stack.
Please read View Controller Programming Guide for iOS before trying to 'switch views' and such. You'll save tons of time and nerves.
another idea is not to use interface builder at all. i have been working with iphone apps for two years now and found that interface builder really prolongs the time to actually make something. make your own root controller and think about the logic you need to navigate through the views.

How do I pass a variable to a childController of UINavigationController based on the selected UITableViewCell

Imagine a simple Navigation based iPhone app.
The top level is a tableView with cells that read "PDF1" "PDF2" "PDF3" with disclosure indicators. Let's call the top level controller "RootController."
When you push the cell labelled "PDF1" a child controller class called "PDFViewerController" is pushed onto the stack which builds a new screen and loads "PDF1" in it's UIWebView.
Now imagine we go back to the tableView and push the tableCell "PDF2." This time the same "PDFViewerController" is pushed onto the stack but now it knows to load "PDF2".
The way I'm doing it now I have to write controller classes for PDF1, PDF2 and PDF3 creatively named "PDFViewerController1","PDFViewerController2","PDFViewerController3".
The thing is the only difference in these classes is the NSURL and it would be much less redundant code to be able to pass in the right NSURL based on a tableCell selection.
I feel like I'm missing something fundamental about OOP here. It'd be great if someone could point me in the right direction. I'm not even sure what kind of string to google to solve this. If someone can suggest a better title for this thread that might help others too.
Thanks.
Create an init method for PDF view controller with an extra parameter, then, in the didSelectRowAtIndexPath: method:
PDFViewController *pdfvc = [[PDFViewController alloc] initWithNibName:#"PDFViewController" bundle:nil andURL:(NSURL *)[myURLS objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:pdfvc animated:YES];
[pdfvc release];