passing Data from AppDelegate to UITabBarController

Discussion in 'iOS Programming' started by rubyruby, Apr 28, 2009.

  1. macrumors member

    Joined:
    Jan 28, 2009
    #1
    Hi,

    how do I pass a data model (which I've created on my own) to the UITabBarController (which is my root view) in my AppDelegate?

    The problem is, that UITabBarController (e.g. addController) doesn't include
    my model (e.g. addController.model). So I would have to subclass it. Is this a proper solution?

    Regards,

    rubyruby
     
  2. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    Do it the other way round. Any instance can get a pointer to the app delegate so simply provide an accessor method for the data model there.

    Or make the "root" of your data model a singleton object and access it that way.
     
  3. thread starter macrumors member

    Joined:
    Jan 28, 2009
    #3
    Thanks, the way you've described it, is my current solution. But I've read, that it would be better design to have a model, which "wanders" around the views instead of a central one.

    Anyway, the central approach of getting a instance of AppDelegate works. I'll stick with it, until I see some better solutions. ;)
     
  4. macrumors 6502a

    Joined:
    Nov 9, 2007
    #4
    Mmm, whilst sometimes necessary, making everything singletons or accessing the app delegate all over the place seems like a code smell to me.

    If you need to pass data into your controller from your app delegate, just add an accessor (or a property) to your own subclass of UITableViewController, e.g.:

    Code:
    // MyController.h
    
    @class MyModel;
    
    @interface MyController : UITableViewController {
      MyModel *model;
    }
    @property (nonatomic, retain) MyModel *model;
    @end
    
    // MyController.m
    
    #import "MyModel.h"
    
    @implementation MyController
    @synthesize model;
    @end
    
    // YourAppDelegate.m
    
    - (void)applicationDidFinishLaunching:(UIApplication *)application 
    {
      Model *someModelInstance = [[MyModel alloc] init];
      MyController *controller = [[MyController alloc] initWithStyle:UITableViewStylePlain];
      controller.model = someModelInstance;
      [someModelInstance release];
      [window addSubview:controller.view];
      [controller release];
      [window makeKeyAndVisible];
    }
    
    Of course, I'm making assumptions about where your instance of your model comes from and where the controler is initialized (it might be loaded from a nib into an instance variable/property of your app delegate).
     
  5. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #5
    I think it depends, very much, on the exact data model. If there is a single data model and only ever will be then I'd make it a singleton. If you are asking the controller to display a specific piece of data that will be different every time then I'd pass it that data to display.

    The OP did not really give us enough data to work out which case he was in, so I simply suggested the easiest solution from where it sounded like he was.
     
  6. thread starter macrumors member

    Joined:
    Jan 28, 2009
    #6
    Hey guys,

    that's right. I didn't give you much information. I have a handful of models. Anyway, you two worked out nice solutions:

    1. If there's a single model: singelton
    2. If there are many models: subclassing

    Cool.. Thanks Robbie and Luke
     
  7. macrumors 6502a

    Joined:
    Nov 9, 2007
    #7
    I'd still favour the latter solution as it is more flexible in the long run; if having your model object as a singleton is no longer appropriate, you'll have to change more code. I've always considered singletons a code smell and I try and avoid them unless absolutely necessary.
     
  8. macrumors newbie

    Joined:
    May 30, 2009
    #8
    Saving & initializing model in view controller could be a problem if you have multiple views in your app. Upon low memory warning, view controller might re-init (if it's not the current view controller), and that causes your data model to re-create and you lose all the state.

    This can be easily proven with simulator. Add a button in your app to make some change to your data model (as a member of table view controller). Switch to a different view (so table view controller will be pushed into stack). Now send a simulated low memory warning, then come back to your table view controller. Inspect the model data -- you'll find your change is gone. Model is now back to initialized state.

    If you set a breakpoint in your data model's init function and repeat the above, you'll find the data model is re-init'ed when you switch back after low-mem warning.

    I learnt it the hard way.

    Now I store data model as a property in delegate. Everything works very well now. I believe Singleton works well too.
     
  9. macrumors 603

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #9
    And for a small app with a countably small number of objects and models, wasting a users memory and battery life by using layers of properties, subclasses, and notification handlers seems like an even smellier waste of resources to me.

    Just stick a pointer to the model in a global. Or if the apps total state data is small enough, just put them all in global variables. One less level of indirection to potentially trash your CPU cache.

    Not every class needs to be designed to scale to 1000's of instances collaborating remotely. Remember that all this dynamic OOP stuff, while good for the developer, can be bad for the users battery life. Spend some time thinking about them.

    imho
     
  10. macrumors 6502a

    Joined:
    Nov 9, 2007
    #10
    This is completely wrong.

    The default behaviour of UIViewController when handling low memory warnings is to release and reinitialize it's sub-views. The entire object isn't released and re-initialized. Your properties will be safe.

    Obviously if you re-initialize the controller yourself you'll need to pass the same model object back into it.

    Or you could just make sure your model object is saved when the view changes.
     
  11. macrumors 6502a

    Joined:
    Nov 9, 2007
    #11
    I'm not a big fan of premature optimisation. Good design first, optimise later. Good design isn't necessarily about scaling, its also about making things easier to test and refactor. Sure, for a small toy app you can probably get away with stuffing everything in your app delegate but for anything else I'd stop using the app delegate for what it isn't intended.

    I don't buy the argument that having a few more classes and objects (i.e. a less coupled design) will make that much impact on the user's battery life. Got any comprehensive figures to back that up?
     

Share This Page