Structuring iPhone/iPad application views - iphone

I have an idea about an application that I want to build and Im new to iPhone/iPad development (but not new to development in other languages/frameworks such as .NET and Java). I want to layout some views on the screen so that they animate (slide in) from different directions into their places.
The question is about the strucuture of the application, if I have say 4 rectanglular areas on the screen that contain business data, such as contacts (name, photo, etc...) and they all take up different widths of the screen (say the first contact takes up one row of the screen, but the next 2 take up half the width of the next row each, and so on).
Should I create a custom view for the different sized contact views, (i.e. LargeCustomView and SmallCustomView, and any other special type that I make) or should it all be one type, say, CustomerDetailsView which could be stretched to fit at design time?
Also, if there were, say, 3 different instances of the same custom view on the one screen, are there 3 instances of the view controller also? Im a little confused about powering the data behind a view, can someone shed some light on this for me? Do I just set the properties (say an instance variable ContactForView) on the view controller for each instance?
Thanks for any help you can give
Cheers,
Mark

Should I create a custom view for the different sized contact views, (i.e. LargeCustomView and SmallCustomView, and any other special type that I make) or should it all be one type, say, CustomerDetailsView which could be stretched to fit at design time?
I think only you can answer that question. If UIView autoresizing masks are enough to accomondate both layouts, you should probably go for just one class. If that's not enough, you can either override layoutSubviews to account for different sizes or perhaps go with a common superclass to contain the logic and two subclasses to do the different layouts.
Also, if there were, say, 3 different instances of the same custom view on the one screen, are there 3 instances of the view controller also?
Because of the way UIViewControllers work, Apple generally recommends not having more than one view controller per screen. From the docs:
You should not use view controllers to manage views that fill only a part of their window—that is, only part of the area defined by the application content rectangle. If you want to have an interface composed of several smaller views, embed them all in a single root view and manage that view with your view controller.
Otherwise, things like device rotation can get tricky as a view controller that is not full screen should probably react differently to such events and Apple's UIViewController is not written to do that. However, nobody stops you from writing your own view controllers (derived from NSObject, not from UIViewController) so that's what I would recommend: if the view is quite complex, write a custom controller class for it but stick to one UIViewController per screen.

Related

Multiple hosting views, each with a different graph/chart

I have a ScatterPlot displayed within a CPHostingView which takes up the bottom 25% of the screen (the hosting view is 320x100).
Now i would like to display a Pie chart at the top of the view (maybe 50x50, roughly).
What do i need to do to make this possible?
My research suggests that i shouldnt create multiple instance of CPXYGraph and that i should just use multiple CPHostingViews.
Problem is, my hosting views do not take up the entire screen, thus, im having trouble determining how to render a pie-chart in one view and a scatterplot in the other.
You should use multiple hosting views.
The Core Plot hosting view is a subclass of UIView on iOS. It inherits the standard view layout mechanism from UIView. Set the autoresizingMask in code or in Interface Builder.

How to design code architecture when overlapping objects exist?

I have 1 main Master screen (MVC) and 4 other screens that share ~80% of graphic objects. They differ in some label texts, a button with action and some other 20% graphics. Thinking in terms of clean object oriented code architecture, I have started to implement those screens as separate UIViewControllers. But I didn't like having pointers to those 4 MVCs and a duplication of some methods, so I rewrited the code into one UIViewController. Most of graphic objects are UIImageViews that I put on with Interface Builder. So, now the xib file of that "unified" UIViewController is a little bit bloated with overlapping objects from those 4 screens. I also need to have those methods like showScreen1, hideScreen2, showScreen2, hideScreen2, and other methods, so I'm not very happy with this architecture too. I understand that I should not mix those 4 MVCs (screens) and both the code, and xib files would be cleaner but I'm also thing about performance, saving memory loads and etc. What would be your opinions on that? How much memory resources takes the loading of separate UIViewController? Maybe the amount of saved memory is not worth when compared to code cleanness? Again, having 4 separate MVC's would force me to have 4 pointers both to my Master MVCs and 4 pointers to those separate MVCs from my Master MVC, because I need to communicate and navigate between those screens. Another option would to use notifications instead of pointers but it doesn't change the amount of required relations. So please share your thoughts and insights :)
For user interface controls that share the same design perhaps you could use categories, this is what I'm doing in a project. I've added a category to UINavigationBar to show a texture on the bar, added a category to UIBarButtonItem / UIButton for a back & cancel button and since my ViewControllers all share the same background image I've created a UIViewController subclass that contains the default background image - every view controller used in my app inherits from this default view controller.
I would stick with 1 view controller per screen.
Apple doesn't recommend creating giant nibs, this is especially visible in the WWDC 2011 video on storyboarding (check this video out if you're a registered Apple developer). Giant nibs are bad in terms of performance, it takes a lot of time to load all objects and all the objects from the nib stay in memory all the time, even if the objects are on a screen that's currently not being displayed. It's a better approach to have a separate nib per screen.

Design options for iPhone app with numerous (~50) screens, each with the same background

I'm writing an iPhone app (which will be my first ios app) that has about 50 screens, each of which has the same background - where the background is an image covering the entire screen real estate and another image at the top as a banner.
Each screen will have some text along with 0, 1, 2 or 3 buttons appearing beneath the banner image.
What is the best design for putting this together?
The options I could think of were (in every each I was planning on having a root controller which is responsible for displaying each view as appropriate).
1) Have 50 separate screens as xibs (and associated view controllers), each of which contains the two background images plus however many buttons each particular screen needs.
2) Have 4 superclasses as xibs - (representing no buttons, 1 button, 2 button, 3 buttons) and have each of those contain the background images and as many buttons as appropriate. Then have 50 subclasses which simply just set the text and button content as appropriate using the superclasses instance variable outlets.
3) Have the root controller have a view which contains the two background images which is there permanently, and each of the 50 views displays its text and buttons on top of that.
4) (If this is possible, I need to check if a window can have images). Same as 3, except the root controller doesn't have a view, the main window displays the background images and each class displays its text and buttons on the top of this. So each view controller would have to load and display the text and button objects using code (in which case there's not much point to have xibs for them).
Is there another solution? Is one of these the "best" solution?
If I went with 3 would it not be possible to define the position text and buttons in a xib? (because in order to do so they would need a parent view in order to position them in interface builder, but if that were the case then when the view is drawn the background wouldn't be visible).
If 4 is possible, then the root controller has no view, therefore does it still need to be descended from UIViewController, or could it simply be descended from NSObject?
I think at the moment I am leaning towards option 2) as that way I can design all the views visually as xibs, but there are only 4 of them. Unless there is a better more elegant solution.
TIA
What you can do, is one XIB with all the buttons and then you would set then hidden accordingly. Although it would tie you up a bit. The 2) option is more flexible. The 3) is ok too. You could have one rootViewController, just to hold the images and then you could something like this:
[rootViewController.spaceForMyChildView addSubview: myNewViewController.view];
The "spaceForMyChildView" would be a view that would hold your child views.
I would do fusion between 2) and 3) probably.
UIWindow inherits from UIView, so can have anything within it. So (4) is feasible, though you're starting to get into tricky water if you want to support any sort of view rotation.
I'd think an inverted (2) would be the easiest thing — have a single superclass that upon viewDidLoad adds the background and top banner programmatically. Have your specific controllers inherit from that and design them graphically to contain whatever you want, mindful that the image and banner will subsequently be added.
That said, if your views are really as simple as a single text area and up to three buttons, always with fixed positions, then it sounds like a single view that repopulates its fields from a data source, as Jacky Boy suggests, is probably the smartest thing.

Iphone - Drawing into a view : philosophy and interactions

I've understood that I need to subclass a UIView t be able to draw inside it.
The thing I don't understand yet, is the philosophy of the way i must be done...
Let's say I have a view controller, and depending on context, I may want to draw a line into one of the subviews it manages, or a circle, or a rect, or a processed graphic. Or lets say two points that are moving inside a view into a defined rect and that display a bigger point when they are close.
How may I subclass and define the subview to make it able to do this only into its drawRect method ?
How does the controller, that manages more than this simple UIView (let's imagine you have a view controller that manages a view inside which there are many other view, and you want to make some drawings in two of them), and that knows what is needed to be drawn into the correct view (it's a controller, isn't it ?), may interact with the views ? And when the drawing is done, how may the views interact with the controller ?
I've read many doc about drawings (apple, web, forums, tutorials, ...), but I still can't touch the philosophy of the way this must be done.
it's very simple. Make a new class, OliverView, which is a UIView. (ie, it is a subclass of UIView.) In that view, make it draw stuff in a fancy way, inside drawRect.
Now make a UIViewController, called OliverVC. In storyboard put an OliverView inside OliverVC. (beginner explanation of how to do that).
In the OliverView, have properties "hours", "minutes", "seconds".
Now, in OliverView - in the drawRect - have a fancy way to display those values. (Pie chart, glowing letters, animation - whatever you want.)
Now, up in OliverVC, do some calculations to determine the time in Zimbabwe, for example.
Once you want a time displayed, simply set those properties in OliverView - - and you are done.
Your colleague could be programming the OliverView. You need know nothing about how she is going to display the time. Conversely, your colleague need know nothing about your calculations in OliverVC..
So, it's simpleL One part has the job of displaying the data. One part has the job of coming up with the data (doing whatever sort of calculation is relevant in the app).
It's the only architecture possible in a "real time" screen device where the views can and do change at any time.
In answer to your question below: you've forgotten that quite simply, if you have a button that would be a whole separate element. (Perhaps sitting "on top of" the OliverView.) So, it's easy!
The -drawRect method in your UIView subclass defines the onscreen appearance of the view. All drawing is done in -drawRect. Your UIViewController calls methods on its UIView to tell it to draw something differently or to perform some other action.
The UIViewController manages everything to do with the view that is not inherently associated with the drawing of the content. Data associated with the view is often stored in the controller.

iPhone/Obj-C: Accessing a UIScrollView from a View displayed within it

I'm writing a simple iPhone app which lets a user access a series of calculators. It consists of the following:
UITableViewController (RootViewController), with the list of calculators.
UIViewController + UIScrollView (UniversalScroller), which represents an empty scroll view - and has a 'displayedViewController' property.
UIViewController (Calculators 1-9), each of which contains a view with controls that represents a particular calculator. Each calculator takes 3-5 values via UITextFields and UISliders, and has a 'calculate' button. They can potentially be taller than 460px(iPhone screen height).
The idea is:
User taps on a particular menu item in the RootViewController. This loads and inits UniversalScroller, ALSO loads and inits the UIViewcontroller for the particular calculator that was selected, sets the displayedViewController property of UniversalScroller to the newly loaded calculator UIViewcontroller, and pushes the UniversalScroller to the front.
When the UniversalScroller hits its 'viewDidLoad' event, it sets its contentSize to the view frame size of its 'displayedViewController' object. It then adds the displayedViewController's view as a subview to itself, and sets its own title to equal that of the displayedViewController. It now displays the calculator, along with the correct title, in a scrollable form.
Conceptually (and currently; this stuff has all been implemented already), this works great - I can design the calculators how I see fit, as tall as they end up being, and they will automatically be accommodated and displayed in an appropriately configured UIScrollView. However, there is one problem:
The main reason I wanted to display things in a UIScrollView was so that, when the on-screen-keyboard appeared, I could shift the view up to focus on the control that is currently being edited. To do this, I need access to the UniversalScroller object that is holding the current calculator's view. On the beganEditing: event of each control, I intended to use the [UniversalScroller.view scrollRectToVisible: animated:] method to move focus to the correct control. However, I am having trouble accessing the UniversalScroller. I tried assigning a reference to it as a property of each calculator UIViewController, but did't seem to have much luck. I've read about using Delegates but have had trouble working out exactly how they work.
I'm looking for one of three things:
Some explanation of how I can access the methods of a UIScrollView from a UIViewController whose view is contained within it.
or
Confirmation of my suspicions that making users scroll on a data entry form is bad, and I should just abandon scrollviews altogether and move the view up and down to the relevant position when the keyboard appears, then back when it disappears.
or
Some pointers on how I could go about redesigning the calculators (which are basically simple data entry forms using labels, sliders and textfields) to be contained within UITableViewCells (presumably in a UITableView, which I understand is a scrollview deep down) - I read a post on SO saying that that's a more pleasing way to make a data entry form, but I couldn't find any examples of that online. Screenshots would be nice. Anything to make my app more usable and naturally 'iPhone-like', since shuffling labels and textboxes around makes me feel like I am building a winforms app!
I've only recently started with this platform and language, and despite being largely an Apple skeptic I definitely see the beauty in the way that it works. Help me solve this problem and I might fall in love completely.
Dan
If you have the particular calculator view, you should be able to get to the scroll view via the superview property (though there might be more than one intermediate view, so you might need the superview of the superview).