Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
I have 3 UIViewController for 3 different XIB windows that gets pushed in by the navigationController. There is a button on the second page that when pressed pushes the 3rd pushViewController. When that button is pressed it also goes to a website and downloads a list of names to populate an UITableView.

My Question: When the program launches that would be the ideal time to load the names from the server and store as strings in an NSArray, not when the button is pressed on the second page. How would the secondViewController access the information on the firstViewController Instance variables?

If secondViewController was a subclass of firstViewController I could gain access to that instance variable values, correct? Then the firstViewController would be subclassed from UIViewController. This way all of my viewControllers first, second and third would inhearit from UIViewController?

This would link all of the controllers together and I could use any instance variables from each super class which I could get information from that variables?

Is my thinking there right?
 
If secondViewController was a subclass of firstViewController I could gain access to that instance variable values, correct?

Incorrect. Since secondViewController and firstViewController are separate instances, they each have their own sets of instance variables. That's why they are called 'instance' variables.

If you want secondViewController to have access to firstViewController's instance variables, you would need to give secondViewController access to the firstViewController instance.
 
I see. To give it access to my instance variables in FirstViewController I would then need to #import my firstViewController in my secondViewController.h.
 
I see. To give it access to my instance variables in FirstViewController I would then need to #import my firstViewController in my secondViewController.h.

That's step 1. Step 2 is you'd need to give your secondViewController an actual instance of FirstViewController (or firstViewController, or whatever the real class is).

Importing the @interface of a class simply tells the importing code what the structure of the imported class is. That is, it tells the importer what the names of the instance variables are, what the methods are, etc. It doesn't actually create an instance anywhere.

Remember, a class is just a factory for creating instances that have the same characteristics (same instance variable names, same methods). You don't make a milkshake by putting a cow into a blender. The cow makes milk, which is what goes into the blender. The cow is a milk factory. A cow is also a calf factory, but the calf instances can be male or female, so not every instance produced is another milk factory. And if you want to make chevre or pecorino, you need a completely different factory (goat or sheep).
 
Thanks Chown33, I get it for the most part and when you mentioned a couple things I remember I did read about that like the #import.

When my app starts I have this code run in the firstViewController.m that fetches the names
Code:
- (void)viewDidLoad
{
    int location = 0;
    if (nameArray == nil) {
        nameArray = [[NSMutableArray alloc] init];
        myURL = [NSURL URLWithString: @"http://something:something@www.sbtraveler.tv/ios/test/name.txt"];
        bundeledInformation = [[NSString alloc] initWithContentsOfURL:myURL encoding:NSUTF8StringEncoding error:nil];
        
        for (int i = 0; i < 4; i++) {
            NSScanner *scanner = [NSScanner scannerWithString:bundeledInformation];
            [scanner setScanLocation: location];
            [scanner scanUpToString:@"\n" intoString:&tempString];
            location = [scanner scanLocation];
            [nameArray addObject:tempString];
            NSLog(@"Item: %@", [nameArray objectAtIndex:i]);
            LabelTest.text = @"it's created";
        }
    }
    else
    {

        LabelTest.text = @"Yes to Array";
    }
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
}

This sets up the NSArray to store the string values that I use for the table views. Now in secondViewController if I need to create a new instance of the firstViewController Class, then it would need to reload all the information from the web again since it is a new object.

I might be going about this the wrong way in trying to set up global variables that all my objects can access.

Thanks
 
If your app needs a single set of data shared by different controllers, then Step 1 of the design is to decide where the single set of shared data will reside.

If you put the shared data in one of your controllers, then you also have to arrange for that data to be made available to (shared with) all the other controllers.

If you put the shared data in a single common place, such as the application object, then any of the controllers can get it, without you needing to make the controllers share the data.

This type of design (a single repository for shared data) is a common pattern. It applies in many cases, regardless of what kind of view or view controller is being used. It's called the Singleton pattern, and it's specifically mentioned and described in the "Cocoa Design Patterns" heading of the Cocoa Fundamentals Guide:
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CocoaFundamentals/

Depending on what the shared data actually is, another possible place to store the shared data is in the application's NSUserDefaults object. See the class reference doc.

In any case, you need to think about the design of the app before writing code for any classes. Think about what's shared and what's not. Where shared things will reside. Where unshared things will reside. Draw simple block diagrams showing relationships of where things are stored, which things can access them, etc. It doesn't need to be complicated, and you don't need a fancy drawing app. Paper and pencil suffices.
 
I couple weeks ago I started to put the design to paper for the project. I do these little tests to see how things work. I used the NSUserDefaults on a projects a few moths ago. I did not think of using that object as a common place to put Ivars that all objects could access.

I will look through the information. Thanks for giving me a push in the right direction.
 
[1]
Try factoring out your networking code into a custom model class. Your view controller is just responsible for instantiating this model; the model is responsible for handling the download and parsing:

Code:
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    if (myModel == nil)
    {
        myModel = [[FirstModel] alloc] init];
    }
}

[2]
Be careful with the synchronous download APIs. Try incorporating asynchronous NSURLConnections to download your information from the server.

[3]
Try having your child view controller declare a read-write property for a model object that it needs to display its data. Then, have the parent view controller set this property to the right data when the child view controller is about to be displayed.
 
I used the NSUserDefaults on a projects a few moths ago. I did not think of using that object as a common place to put Ivars that all objects could access.

As a general-purpose place to put shared variables, NSUserDefaults is a poor choice. That's just hammering a square peg into a round hole.

That's why you need to think about the design before thinking about how to implement a design. In other words, step 1 is creating a design. Step 2 is implementing it. You don't choose NSUserDefaults or some other class until step 2.

When you do it backwards, then the first choice you make is NSUserDefaults, and you then cobble together a design around its strengths and weaknesses. If what you're trying to do happens to be a bad fit for NSUserDefaults, then you will spend more time and effort trying to make it fit than if you just started over from scratch.

If you have a good clear design, it should be obvious whether to use NSUserDefaults or not. Without a clear design, you can't possibly make a sensible choice of how to implement it.

I'll use another analogy: if you're making a video short story, do you start by shooting actors in on-location scenes? Or do you start with an idea of the story you want to tell, then write a script, then decide which actors and locations to use? Even with a script, actors, and locations chose, are you ready to shoot yet? Not likely: you have to decide which shots are closeup, which are distant, from what point of view, what time of day, whether you need a dolly and crane operator, etc. When you do it backwards, you end up with nothing but a bunch of meaningless crane and dolly shots, of incongruous actors saying meaningless dialog.
 
Last edited:
The more feedback I get the more I need to learn. I am at a frustrating point where I understand the concepts but get a little lost applying them.

Chown33 - I hear you. 'Top Down Design'. My pascal teacher would hit us over the head all the time. 90% planning and 10% coding. I am still learning a lot about coding so I am creating these small project to better understand as I work myself to my over all goal. This is helping me with planning. I use OmniGraffle to help me design what I want. I am very thankful and I think you can see after all this time that I am working hard. It's tough learning object C from a book and the internet forums.

North Bronson - Thanks for the pointers. I just started iphone a couple weeks ago but start object - C before summer. "synchronous vs. asynchronous". You lost me there and I will look it up and learn it. But thanks for the push in the right direction.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.