PDA

View Full Version : confused about planing a project for the iPhone




MACloop
Nov 17, 2009, 04:11 AM
Hi all!
I have been developing awhile for iPhone now and have really tried to understand the structure to use when organizing a programming project.My problem is that it seem to be described in so many different ways. I have 2 books and have also followed several tutorials on the internet. Additionally I have read and modified the sample code from apple, in order to try to understand but the result is me being a bit confuced :confused:

My problem is perhaps abit easier to understand if I make an example:
I have a first view with a tabBar (below the actual content). When pressing one of the items on the tabBar another view should appear. This is easy and could be implemeted like the tabBar ex. from apple. The problem is that those views appearing when I press the tabBar items, also content views, like mapViews, tableviews and other stuff. The tabBar should be visible in each and every view that appears on the screen.

I started to build every single view and my intention is to let the views to be independent of each other. Every view has a viewcontroller.h and .m and I have created proper classes used by the views, like parser classes and other things. This is rather trivial, but the problem is to get it all work together. Should I see every view as described above, as a independent application, in the total application. If yes - should every view have its own appDelegate defined as a file?

Summerized questions are:

1) How do I structure many independent views optimally to work in one application?

2) Should there be only one appDelegate or should I define one for each viewcontroller? In a bigger project is it possible that the viewcontroller has an object created from another viewcontroller... for example: view2 contents a mapview and the view2 is visible in the mainview. View1 contents a tableView and by clicking on the tabBar (should the tabbar be aview to?) the view1 or the view2 are called and displayed...

3) The "main-view" is one of the views - aka the first view that will appear on the screen... If I would like to change to another view, do i have to create an object of the other view in this first view and make it a subview of the first view? Or should I in the appDelegate make all the views subviews of the window? If yes - where do I control whicht view to be visible at the moment? My thought here was to, when tapping one of the items on the tabbar, the current subview attatched to the tabbar item should be moved to the front like:- (void)bringSubviewToFront:(UIView *)view

I hope that someone could help me out here, because I really do want to understand this in order to make my apps more effective and roboust.

Thanks in advance!
MACloop



RashiMahajan
Nov 17, 2009, 07:57 AM
Yes its possible to send one view object of other view which is in some other class, & then u can access the property of the instanced view in present class also & can set them

MACloop
Nov 17, 2009, 08:57 AM
Yes its possible to send one view object of other view which is in some other class, & then u can access the property of the instanced view in present class also & can set them

Thanks for your answer! I have found out that it is possible but I wonder how the structure should look like to make it as optimized as possible. I think it is hard to follow the code and hard to keep it structured if you create classes/views that are dependent on other classes, that are dependent on other classes...it becomes a chain of dependencies and that is not exactly what I have learned to be effective programming.... I am sure I have understood something wrong... Perhaps anyone would like to show me an UML or something like that, showing a bigger project...?
Thanks in advance!
MACloop

PhoneyDeveloper
Nov 17, 2009, 09:23 AM
The tab bar controller manages which view controller is the active view controller. If you use a tab bar controller then you don't add subviews to the window.

Both tab bar controllers and navbar controllers can manage the current active view controller. It's best that you use those classes for this purpose.

There is only one app delegate. It's a singleton.

Only one view controller is the 'active' view controller. In most ways each view controller will be isolated from the others. However, it's possible to have global data that's accessed by more than one vc as well as messaging between view controllers. If you use global singleton objects for your app data and messaging with the notification center your vc's should not have many dependecies on each other.

MACloop
Nov 17, 2009, 09:44 AM
The tab bar controller manages which view controller is the active view controller. If you use a tab bar controller then you don't add subviews to the window.

Both tab bar controllers and navbar controllers can manage the current active view controller. It's best that you use those classes for this purpose.

There is only one app delegate. It's a singleton.

Only one view controller is the 'active' view controller. In most ways each view controller will be isolated from the others. However, it's possible to have global data that's accessed by more than one vc as well as messaging between view controllers. If you use global singleton objects for your app data and messaging with the notification center your vc's should not have many dependecies on each other.

Thanks alot! Your answer made things abit clearer! How would you suggest to mark a view as 'active'? In the delegate? In one of the viewcontrollers? Suppose that I have 5 views and 5 tabs on my tabbar. Which file should I use as tabbardelegate? Where should I define the objects for every one of the 5 viewcontrollers?
/MACloop

PhoneyDeveloper
Nov 17, 2009, 10:05 AM
How would you suggest to mark a view as 'active'?

This is somewhat under user control. If a user selects a tab in the tab bar then that vc becomes the active one. With a navbar anytime you use pushViewController: or presentModalViewController: you are setting the active view controller. Hitting the back button is under user control and changes the active vc. There are a set of callbacks that notify your code when these things happen. viewWillAppear/disappear etc. In most cases you design and implement each vc so that it does the right thing relative to responding to those callbacks and pushing/popping any other view controllers that are required.

Actually I haven't built a tab bar app so I can't answer your direct questions about their details.

Luke Redpath
Nov 17, 2009, 06:39 PM
If you use global singleton objects for your app data and messaging with the notification center your vc's should not have many dependecies on each other.

Although, and I've said this on here before, try to avoid going the singleton global object route if you can avoid it. It's far better to pass the dependencies for a controller into the controller either at initialization or using a property.

E.g. if you have a SongsController which requires an Album (that it will display the tracks for) instead of doing this:


// in SongsController somewhere
self.album = [[MySuperGlobal sharedInstance] findAlbum];


Do this:


// in the preceding controller, perhaps an AlbumController?
SongsController *sc = [[SongsController alloc] init];
sc.album = self.album;
[self.navigationController pushViewController:sc];


Introducing singletons should be a last resort as they make your code much more coupled and harder to unit test.

A similar, but just as bad (if not worse) anti-pattern if you will, is to try and stuff lots of shared stuff into your application delegate and access it from everywhere. Don't do this. Your application delegate is there to act as a delegate to UIApplication and do initial setup. The clue is in the name.

I firmly believe that maybe 90% of the cases where people try and use some kind of global manager/singleton object there is often a better way of doing it (will try and back that up if somebody wants to point out some examples).

Luke Redpath
Nov 17, 2009, 06:45 PM
Just to expand on that a bit further, if I really do need to use some kind of singleton object (because it makes sense for there to only be one of that particular class in my app), I still try to pass this around as a dependency rather than accessing the singleton directly within a class so I'm not coupled to my decision to use a singleton.

For instance, if I have a class called AccountManager which needs to download something from a password-protected URL, it will need a username and password.

I keep the user's credentials in a global UserCredentials class. However, I never use UserCredentials inside my AccountManager class whenever I need the username and password. I don't do this either:


@implementation AccountManager

- (id)init
{
...
self.username = [[UserCredentials sharedInstance] username];
self.password = [[UserCredentials sharedInstance] password];
return self;
}
@end


Instead, I define this:


@implementation AccountManager

- (id)initWithUsername:(NSString *)username password:(NSString *)password;
{
...
}
@end


Now, when I construct my AccountManager instance I will get the credentials out of UserCredentials and pass them in, but my AccountManager doesn't need to know anything about this design decision. Low-coupling, easier to test.

PhoneyDeveloper
Nov 17, 2009, 07:54 PM
I don't worship at the alter of unit testing so the effect of global objects on unit testing isn't important to me. Changing working code to satisfy the tools or company policy usually isn't the brightest part of my day.

I don't mean to suggest that global objects are the be-all and end-all to software design. They're another tool in the drawer.

My global objects tend not to be of the [myclass mysharedInstance] variety that Apple favors. Mine are usually a set of class methods. I have, for instance, a file manager class that manages files of certain kinds in the Documents folder. It does have some global state, like a list of the current files, and it allows the user to delete files. There will only ever be one of these objects and having it as a global singleton is a fine design. It could be implemented as a set of functions, not much different than those in math.h or files.h. Passing around the pointer to this object from one method to another in client classes would be pointless.

The nature of the UI on the iPhone is that you can only view one 'window' at a time and designing apps so that the user can only view one 'document' at a time is common and reasonable. Having a global object that represents the current document is a design that matches this and while that may not be appropriate for every app it's a fine way to do things for many apps.

firewood
Nov 18, 2009, 01:40 AM
Although, and I've said this on here before, try to avoid going the singleton global object route if you can avoid it. It's far better to pass the dependencies for a controller into the controller either at initialization or using a property.


Passing dependencies around just moves your spaghetti from the objects into these linkages. I've seen people create a untangle-able mess of dependencies just trying to avoid a few singleton globals. Go for the solution that is simple and easy to undo. Whether OOP, or Fortran66 style code. Don't swat flies with howitzers for the sake of "style".

If you have a comprehend-able amount of shared state, it's best to centralize it into a few controllers as possible (one, e.g. a singleton, if the amount of state is small enough), with accessors to control state consistency, if needed, as well as the ability to core dump the entire app state from one place for debugging, without having to hunt around.


Introducing singletons should be a last resort as they make your code much more coupled and harder to unit test.


Sounds like religious nonsense. Computer science is based on one big singleton, the Turing machine. So is most actual hardware, once you get to the physical address spaces. People who don't understand the theoretical and physical basis's for computing often don't end up with the skills needed to keep an app under a strict battery life (mAH) budget.

MACloop
Nov 19, 2009, 02:03 AM
Hi again!
Thank you all for very interesting and helpfull answers. I will try your advice out right now!
/MACloop