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.
Related
A couple of weeks ago i have started my research in Iphone app development and after alot of hello world applications in different settings i am now ready for my very first application based on the MVC design pattern used in Cocoa.
This opens up alot of questions for me though and after reading the different class references about UIViews and controllers i am stuck in trying to figure out which one i should be using.
In my application i am trying to create a grid of small rectangle's with each rectangle having a different text value on them, to be more specific, i am trying to create a simple calender that will display all the days of a month in a grid.
Every rectangle is a instance of a class i named Tile, in this class i want to implement the drawRect method to draw the rectangle for me and set the text value to the day it should represent.
In order to implement this i have done some research on how this should be done.
From what i have learned so far is that UIViewcontrollers do not really display anything, they are basically sitting there waiting to respond to any events from their children.
In my application i would translate this to the Controller that will respond to each touchevent on a tile.
A UIView however is also a container but one for objects that will need drawing methodes like drawRect. This would translate to the grid that will hold all of the tiles if i'm correct.
Except, i have no clue what subclass i should use for each tile, i have the feeling i am really missing some basic knowledge here but i just can't figure it out. Would really appreciate it if anyone could point me in the right direction with this.
If there were any two apple document you should read, it is the one about UIViewControllers which can be found here and the one about UIViews which can be found here. The UIViewController, as you mentioned, is more about integrating with the iOS system than being a visible component. It has a reference to a UIView, and that UIView is the root node in the visible tree of elements which starts at that View Controller.
In iOS programming you don't really need to worry about drawing rectangles, because for the most part you will be extending elements which know how to draw themselves and then just telling them where to go. The basic visible element in this case, is the UIView. There are many different kinds of UIViews (see the graphic in the UIView programming guide link), so for your case you could use a simple UIView with a background image set to your calendar box graphic, and add a subview of type UILabel. UILabel is a subclass of UIView, so you know it will be something visible as well.
Once you grasp these concepts (which can take a long time) Interface Builder will start to make more sense and you can start doing some of these things with it - and understand how its working. In essence it will create the hierarchy of a UIViewController referencing a hierarchy of UIViews automatically, then you.
Tile should be subclass of UIView since you want to drawRect your "days". Then you can add as many Tiles as you want to your UIViewController.view and manipulate them from UIViewController code (.m file).
But you can add UILabels to your Tile view and manipulate them by setting their text property. In this case you won't need to override drawRect: at all, UILabel will do the rest for you, but you will have to programmatically add this labels to your Tile (e.g. in Tile's init method) or in Interface Builder. In the last case you will have to load them from XIB using [[NSBundle mainBundle] loadNib:owner:options:] method.
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.
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.
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.
alt text http://www.davidhomes.net/question.gif
I'm farily new to iphone dev (<3 months on my free time) and I'm starting development of my second app.
From the image, I'm adding a number of UIViews as subviews to my main UIViewController.view, the number of Views to add varies based on user selectable data.
Each view contains several controls, a label, a UITextField and a Horizontal UIViewPicker.
For simplicity I put a (VERY ROUGH) mock-up here with only two buttons.
Because I want to improve the GUI, I want to overlay an UIViewImage as the top sub-views of the added UIView, something like in the image.
The question is on passing through the events to the objects below it. I've read somewhere that one way was to use clipping, but the actual shape is more complex than just an oval frame.
Somewhere else I read that one could add four UIImages, one at each border, which would let the events pass through this hole. Seems like a dirty solution to me (Although I'm sure it would work)
Any ideas about the best way to do this? Any links to a tutorial or recipe online?
Your help is appreciated
thanks
david
Have you looked at protocols? You can define protocols for your views or objects, and the users of that object (the subviews underneath for example) can implement the protocol, set itself as the objects delegate and when actions happen they will notified through the protocols. So for example
An AboveView will declare a protocol that declares methods when a certain gesture was senced by that view so something like
-(void)didMakeCircleGesture...
as a property the underneathview will have a delegate, so in your method that actually sence the gesture youll have at the end something like
[delegate didMakeCircleGesture];
in turn the delegate is the view underneath or something, and it will conform to the protocol defined by the AboveView, and as part of it it will have to declare the method didMakeCircleGesture, so as a result when one makes a circle gesture in the AboveView the underneath view that conformed to the protocol will be told of the event and it can take appropriate action