Which design approach should I take for creating this custom view? - iphone

I'm trying to create a generic, reusable view, that looks like a lined notepad. The way I decided to approach the problem (after a couple design iterations) is to create a custom view that is composed of a UITextView and a UIView.
When the user scrolls through lines of text I want the UIView to track the scroll direction. The key here is: Within my custom view, I need to change the position of one subview in response to events in another subview. Something needs to coordinate these changes...
Now, one approach I thought of taking was to use a MVC design pattern. A view controller could handle all events and move the subviews around accordingly. This MVC could then be embedded in other MVCs.
Normally when using a MVC design pattern, a controller would handle user events and manipulate the model and view. However, my custom view doesn't have a model - all I'm trying to do is have the view manage it's own subviews when a user does something like scroll. It seems to me that the MVC design pattern isn't a good fit here for two reasons:
There isn't a model or logic that is specific to the program it's being used in.
It seems to me that the view should be responsible for handling user events that change how the view should appear.
... but I could be wrong, which is why I'm asking for help. The question, for those who are more experienced than I and who may have done this many times before, is:
What type of design pattern is appropriate in this situation? MVC or...

You want a view to manage its own subviews? Then do that! So what if that pattern doesn't have a TLA?
A typical approach is to implement layoutSubviews in your container view. Have it check its current state, or the state of the other views in the window (e.g. the contentOffset of a scroll view), and then set up its subviews appropriately. (Resize them, reposition them, etc.)
Just try to keep it fast, since it's likely that layoutSubviews will be called frequently.

Related

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).

Cocoa touch view with multiple identical subviews

I'm having my first foray into Cocoa Touch programming (and one of my first into Cocoa in general) and writing a simple game for the iPhone, though this question is about cocoa touch in general.
The main UI consists of a strip of identical acting buttons (only varying in colour) arranged horizontally across the screen. Although they act like buttons they need to have a custom drawn appearance. Each responds to touch events in the same way, triggering other events in the application.
I want to define a custom view, partly to have more control over the behaviour than just having a bunch of standard buttons, and partly to learn more about cocoa programming.
Should I define a main view with an array of subviews each of which draws itself and forwards touch events? Each button should do standard things like show a pressed state when touched and so on. Are there any pre-existing container views for this kind of scenario?
Or should I just define one main view which draws the whole strip and detects where a touch occurs? I feel this is a badly engineered approach - I shouldn't be programming hit test code.
Edited to clarify the question
The more lightweight approach is to add sublayers to your UIView's layer. Use hitTest: to dispatch touches you receive on you UIView to the CALayer instance that needs to receive it.
If you need more of the UIResponder behavior (touchesBegan etc.), you might want to go with subviews instead of sublayers as that would allow you to handle the events directly in the objects rather than having to dispatch them from a central responder (your main UIView).
Consequently, the essential bit may be just how much of the behavior associated with your individual buttons should be known (handled) by the your main UIView. If it makes sense to have everything controlled from a central place, you can put all the logic in the UIView and just use sublayers for lightweight display purposes. If it makes more sense to put the behavior into the buttons themselves, they shoudl be UIResponders and as such subclass UIView and be added as subviews of your main view.
You should use an array of subviews - that way each "button" class knows how to draw itself and its superview (your stated "main view") places the buttons where they need to go.
And second on the NDA: just talk about the iPhone.
If you have a lot of buttons and want to do fancy things with them, I recommend using layers. Your UIView will handle interpreting which layer had the touch (hit testing) and
respond appropriately. If all you're doing is managing a whole bunch of buttons with various effects and animations, this might be an easier route.
As for bad engineering, not at all. If you take a look at the associated guides, you'll see core animation and layers does require hit testing (though that's relatively easy), but it's far cleaner than the UIView doing all the drawing and more efficient than many subviews. It slips right between those two approaches nicely.
Full disclosure: I'm just wrapping my head around how to best leverage this stuff myself, but for more complicated interactive controls.
You can layout your view in Interface Builder. Simply drag a bunch of UIButtons in your view controller's view.
To respond to events, you define an IBAction in your view controller and connect the buttons to it.
This is all very basic. I really suggest that you at least walk through the iPhone programming introduction that Apple has online. It will teach you iPhone and Interface Builder basics.

iPhone: rendering of different views possible?

I have a problem, I can't solve properly.
In short: I want to create a single view (say: UIImageView) out of multiple subviews - i.e. it consists out of multiple ImageViews and TextViews. The thing is, I want to sort of 'render' them to be a single View.
Say, I take an image, add some description below, add a title above, and maybe another little image at the bottom. I want this whole thing to be a single UIImage to make it sort of 'listen' to one (e.g.) swiping gesture, which I cant tell to bring the new image to display.
Does anyone know the best way to achieve this? So far my results were fairly poor.
Any hints are welcome!
This is definitely possible. You seem to know about views and subviews, but should also read up on the "UIResponder" class and the "responder chain". The master view that you want to contain them all won't be a UIImageView, though, because that exists to just show an image. You can make all the ones you talk about subviews (addSubview: or in Interface Builder) of a plain UIView that you subclass yourself (say, MyContainerView), which then itself handles the gestures. If you want to take advantage of free scrolling on swipe, you could instead put your container view into a UIScrollView, which has its own set of semantics that you can leverage. For this latter, you should check out Apple's sample code for scroll views (don't have a link handy but should be easy to find) which embeds multiple image views in a scroll view.

Iphone View explanation in detail (View, Superview, etc)

I'm looking for an in-depth breakdown/explanation of the iphone's view usage. Like, what controllers have what types of views, how they relate (child <> parent), how they can be nested, added and removed, etc.
Preferably something with some pictures would be nice too (I'm a visual learner).
But yeah, in-depth, technical, explanations of the iphone view system when used in IB/Obj-c would be awesome.
Also, feel free to give your breakdown or post to resources and I'll do the research.
Thanks
EDIT:
Ok, I'll be more specific. Is the View a stack - is it a queue? What does it look like when I call addtosubview?
What happens if the view isn't a full UIView, but say a smaller UI Control - will it be visible?
Say I have a UIView with a UITabView (2 items) and one content view is a UITtableView.
What's the parent view? What is the order of the children? Is that all dependent on how I add them to the view? In this case, the UITabBar control takes care of handling the views when I select the button.
When I call insertSubview how do I know what index to position it at?
This will be a good place to start (go from here to UIViewController and others that seem relevant). A UIView can contain many subviews of any type (they all inherit from UIView). To nest views, you add the subview to the superview [superview addSubview:subview]. You should also read up on Model-View-Controller.
Edit:
This SO question might also shed some light on the matter.
Edit edit:
Best I can do to answer your questions:
UIViews have an iVar subviews which is an array of subviews. Each of these also has such an array and can contain UIViews.
I assume you mean not full screen, generally, the topmost view is a UIWindow, and to this you add any UIView subclass you like, such as UISlider.
Your UIView has a subview UITabView, I don't know specifically, but I would guess it has two subviews, one of which is visible at a time, and one of these is the UITableView. Order is dependent on the order you add them in, and they will overlap each other depending on this order, but it can be changed with sendSubviewToBack and bringSubviewToFront.
If you want a specific view order, you're probably better off using insertSubview:aboveSubview: and the equivalent below, rather than at index.
Hope some of this helps.
Ok, I'll be more specific. Is the View a stack - is it a queue? What does it look like when I call addtosubview?
I like to think of it as a tree. The window is the root node, and it has any number of subviews. Those subviews can have any number of their own subviews, going down as far as necessary to create the full interface. The addSubview and removeFromSubview methods manipulate a view's "children".
What happens if the view isn't a full UIView, but say a smaller UI Control - will it be visible?
My understanding is that everything on the screen is a subclass of UIView, even the UIControl objects. Therefore, they behave mostly the same.
Say I have a UIView with a UITabView (2 items) and one content view is a UITtableView. What's the parent view? What is the order of the children? Is that all dependent on how I add them to the view? In this case, the UITabBar control takes care of handling the views when I select the button.
I'm not sure: David's answer has more info that should help.
When I call insertSubview how do I know what index to position it at?
I wouldn't worry about it: most of the time you just want addSubview and you won't care about the internal order.