Help again :( Global Variables.

Discussion in 'iPhone/iPad Programming' started by resetme, Dec 20, 2012.

  1. macrumors newbie

    Joined:
    Oct 28, 2012
    #1
    So, i'm making a simple app that contains 9 views, each one with 3 question, i'm sending the answer from one view to another until the last view, but i would like to set all the answer inside a Global var.

    How can i achieve the global vars?

    1. AppDelegate.h extern Variable?
    2. Global vars using a new class file?
    3. Create a Singleton?
    4. Idk if this work, but creating a class method that set and return a static var.

    every site i check says: this should not be done... :/ so how i'm supposed to do it?

    In my mind i think about creating an answerController class where all my views write on it... but that it's a singleton, ritgh? and i should not use it. Why?

    thanx!
     
  2. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #2
    Singletons are fine; even Apple uses them. Where did you read that you shouldn't use them?
     
  3. thread starter macrumors newbie

    Joined:
    Oct 28, 2012
    #3
    google, forums.

    Tons of people saying that singletons are evil.

    I will use this one:
    Code:
    + (id)sharedManager {
        static myGlobals *sharedMyManager = nil;
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            sharedMyManager = [[self alloc] init];
        });
        return sharedMyManager;
    }
    
    - (id)init {
        if (self = [super init]) {
            someProperty = @"Default Property Value";
        }
        return self;
    }
    
    I saw that you have lot of knowledge in objective-c so i will stick with singletons.


    ty
     
  4. macrumors 603

    Joined:
    Aug 9, 2009
    #4
    You should be thinking about the Model, not a Controller or View.

    Imagine there is a single centralized Model that provides questions and answers. All the controller objects know what the Model is, and how to access it. The Model might be a singleton class. It might be a single global C variable. It might be multiple global C variables. It depends on what you're trying to accomplish.

    Maybe there are 9 separate components in the Model, one for each view. Or maybe not. You haven't said anything about how the questions and answers relate to one another. Do the answers in one set affect what questions are asked in another set? The logical relationship between questions and answers probably belongs in the Model, rather than in any Controller or View. But without knowing what you're trying to accomplish, all anyone can do is guess what a suitable Model design might be.

    If you don't know how to separate the Model element (which may encompass multiple components) from the Controller and View elements, then you need to review the Model-View-Controller design pattern (MVC).
     
  5. thread starter macrumors newbie

    Joined:
    Oct 28, 2012
    #5
    That was a good lecture, now i have another pov. I always make the mistake of creating a "God Class".

    I will do my homework and start from scratch again.
     
  6. macrumors 603

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #6
    Religious nonsense.

    Decades of reliable software (stuff for air traffic control, spaceflight, nuclear weapons, etc.) were written before the object oriented fad. Just know where to use singletons and globals. They are not meant for large or complex projects planned for lots of reuse, extensibility or a decade of maintenance, but lots of code isn't.

    A global variable is just a form of singleton state. So you can create some custom Model classes to hold these state variables. Or the lazy mans way to save the few dozen lines of code needed to create a custom singleton class is to just use the singleton object that comes for free in every iOS app: the app delegate. But if you end up with 20 Model object hidden in your app delegate, that can become unreadable very quickly.
     
  7. macrumors 603

    Joined:
    Aug 9, 2009
    #7
    Not every God Class is a mistake. It depends on what you're trying to accomplish. Just like not every Singleton is a mistake. The problem in both cases (and many others) is thinking it's the solution for every problem. Or worse, not thinking at all about exactly what's in the Model, and what's only in the Controllers, and how one relies on the other.

    A frequent problem when learning how to design Models is there are few good examples that describe the process. There's plenty of fully formed examples, just look in Apple's sample code. But the design process of how that thing came into being is not described. In particular, there's no mention of all the failed designs that were started, reached a certain point, and were then discarded in favor of a better idea. No project I've ever done came into its final form after its first design. There are always failures, and those failures are very instructive about what does and doesn't work.

    If you describe what you're trying to accomplish, people here are often willing to make suggestions about a design. But if all you describe is 9 screens of questions and answers, then no one here can make any useful suggestions about a suitable Model design.

    Also, if you post ideas about designs, and why you're considering them, you can often get suggestions here. But if you work in isolation and don't describe your design process, no one here can make suggestions about how to improve your process.
     
  8. thread starter macrumors newbie

    Joined:
    Oct 28, 2012
    #8
    well, my app are 9 screen, every screen have 1 question with 3 answer, every answer give you a number (+1 to +3). At the end i'm supposed to show a suggestion that varies with the sum of all your answer. My english it's not good enough to explain all my ideas :(

    I decided to skip the singleton and global vars to implemented a property list with all my questions inside an array, and also a holder to store the answer for every screen.

    Plist because i only need to store a small number of int and string.

    This is my first app using xcode and obj-c, and it's not for me, so i'm trying to keep it really simple.
     
  9. resetme, Dec 23, 2012
    Last edited by a moderator: Dec 24, 2012

    thread starter macrumors newbie

    Joined:
    Oct 28, 2012
    #9
    After all i'm using PLIST to store all my Globals Vars.

    I also created a class method to Save the vars and to retrieve it.

    so, inside any class or viewController, if i want the string or the number i just do:
    Code:
    #import "plistClass.h"
     
    NSString *answer = [plistClass getAnswer];
    
    and to store from any class:
    #import "plistClass.h"
    [plistClass setAnsert:@"blah"];
    
    It's like a Singleton, but its not, i don't have to instantiate it or anything.

    problem solved :D
     
  10. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #10
    First, how does your getAnswer method know what the question is?

    Second, plistClass looks like the name of a variable and not a class name. You should consider following standard naming conventions and use something like PlistClass instead. Better yet, maybe something like AnswerHandler that doesn't indicate how you are doing the storing, should you decide to change that, and doesn't say Class, since it's naming and context should make that obvious.
     
  11. thread starter macrumors newbie

    Joined:
    Oct 28, 2012
    #11
    ty for the reply, yes i will change my class names. This is the prototype to test code, then i will follow the name convention you mentioned before with the first Capital Letter for class names.

    About the getAnswer, all my scenes (storyboard) are identified by a number (int).
    So, to write the answer i set:
    [className setAnswer atScene]
    to retrieve
    [className getAnswer atScene]

    the plist are:
    Array[0]
    -Dictionary
    --Key Question = Array
    ---Array[0] string
    ---Array[1] string
    ---Array[2] string
    --Key Answer = Number
    Array[1]
    ... .... ..


    at the end of my app i just loop my root array and ask for the key "answer".

    Code:
    
    +(void)getPath{
        //Fill Array
        questionPath =[[NSBundle mainBundle]pathForResource:@"questions" ofType:@"plist"];
        questions = [[NSMutableArray alloc] initWithContentsOfFile:questionsPath];
    }
    
    +(NSString *)showQuestion:(int) atScene{
        [self getPath];
        
        //Show Question
        NSUInteger randomQuestion = arc4random() % [[[questions objectAtIndex:atScene] objectForKey:@"question"] count];    
        return [[[questions objectAtIndex:atScene] objectForKey:@"question"] objectAtIndex:randomQuestion];
    }
    
    +(void)storeAnswer:(int) atScene ans:(int)ans{ 
        [self getPath];
        
        //Check prev State Answer
        //NSNumber *answer = [[preguntas objectAtIndex:atScene] objectForKey:@"answer"];
    
        [[questions objectAtIndex:atScene]setValue:([NSNumber numberWithInt:ans]) forKey:@"answer"];
        [questions  writeToFile:questionsPath atomically: YES];
        
        //loop for answer
        //answerLog= [[questions objectAtIndex:i] objectForKey:@"answer"];
    }
    
    I stil need to change some stuff because i don't want to have 2 static vars:
    static NSMutableArray *questions;
    static NSString *questionPath;

    but now i'm fighting to upload an image to my server :/
     
  12. macrumors 68000

    Joined:
    Jan 28, 2003
    Location:
    Less lost in L.A.
    #12
    As chown33 mentioned, the following can only be a guess based on the little we know. A few thoughts popped into my head and I thought I'd share them.


    It sounds to me that you are creating independent screens (scenes) for each question (or collection of 3). I think you should create only one such screen that is capable of handling all of the questions and answers. Consider what you would do if there were 10,000 questions. Certainly you could create a reusable screen that keeps track of those +numbers rather than creating a bunch of similar screens that you pass values forward to.


    As for the model and using plists, that is fine for a small list but would likely be a burden with thousands of entries. Use of a singleton as the interface to your questions and answers seems OK. In the future this would allow you to change the underlying data container from a plist to some other possibility like a local database or an web source, but keep the client interface methods the same.

    Here is one idea...

    First, I didn't understand why you are writing back to the questions plist file. That would seem to be a different mode of test app. So the following assumes only the test mode in a Q&A scenario. It looks like there may be more to your app, but the idea I present may be useful for you.

    For the plist, use a dictionary for each question and make the key a sequential number with no gaps. For the questions and answers, the dictionary value, a simple ordered array would be workable. The first entry would be the question, the second entry the correct answer, and any followup entries would be incorrect answers. I'm assuming this is a multiple choice test.

    Your singleton would handle the initial load of the plist (or other future source), fetching a random dictionary entry, a comparison method for the chosen question, and fetch for the correct answer. The three unique methods might look like this;

    Code:
    - (NSDictionary *) fetchQuestion; // Internally chooses a random dictionary entry and returns it, or a copy (see below) preferably.
    - (BOOL) compareAnswer: (NSString *) answer forKey: (NSNumber *) key;
    - (NSString *) answerForKey: (NSNumber *) key;
    
    Your view controller would need to randomize the order of the multiple choice answers for display, otherwise the correct answer would always be answer 1. If you were to use the compareAnswer method above, you could have your singleton reorder the answers in a copy of the dictionary. You could do that because then there is no reason for the view controller to know the correct answer in the dictionary in this scenario.

    One weakness of the plist key is that if you skip a number during creation, your randomized selection would be broken. To fix this problem, it would be prudent to implement a solution to avoid that. I think a simple array of all of the keys would be workable. You'd pick the key from that list via your random number based on the array count.

    By using a dictionary and key, you don't have to perform that looping. Also, I see you were loading your question multiple times but you wouldn't need to do that time consuming operation more than once if using a singleton because you would load it during initialization.
     
  13. thread starter macrumors newbie

    Joined:
    Oct 28, 2012
    #13
    hi ty for your time.

    The other day i though about one scene (1 storyboard) and load all my question there, but, sadly i don't know how to do that :(

    Inside my view, another view with my label and buttons? And create everything by code? Sounds good, but i have no idea how to start it without linking my buttons in Xcode...

    Maybe, press the answer, call reload method, get everything back, ++i for question and change title, animate all...i will lose my modal animation. So i will have to fake the modal and then get the view back. oh so many question, but i will try.

    I'm randomizing the answer buttons with animation, every time the scene start i move it to the center and then animate back to new position.

    Well, all answers are correct, but each one have a value, the sum of all answer is the feedback at the end. (i'm not in charge of that)

    I'm not writhing back the question... well i think not, i will take time to check it again.

    About the loading the question multiple times... i don't know, everytime i call my [className showQuestion atScene] i'm loading it again (like multiple instances) ? That would be a waste of resource...
     
  14. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #14
    Seems to me that having each question defined in it's own scene is also a waste of resources.

    Based on the kind of questions you are asking, I'm unclear on how well you understand the fundamentals of iOS / Objective-C programming, so perhaps you could explain (try to be a specific as possible) what resources you are using to learn the basics of iPhone programming.
     
  15. thread starter macrumors newbie

    Joined:
    Oct 28, 2012
    #15

    This is my first time with objective-c 2.0. i Have an app but was made in C#.

    iOS SDK Essential Training (2012) - Simon Allardice
    Objective-C Essential Training - Simon Allardice
    Foundations of POO - Simon Allardice
    Programing in Objective-c 2.0 - Stephen G. kochan
    Iphone sdk 4 Dev - Mark Lamarche

    Very basic, there is a lot of stuff that i don't get it at all.

    But every book/video say the same; "embrace confusion"

    Today i will start again using only 1 screen for all questions.
     

Share This Page