A question about CALayer and UIView - iphone

The object is to implement a semi-transparent layer which would slid out to collect user response when needed. The semi-transparent layer would have some icons on it for the user to choose from. Currently I am using a CALayer object which seems ok and it has some build in animation behavior.
But the problem is CALayer does not response to any touch events at all. Now I am thinking that I should be using a UIView instead. UIView inherits from UIResponder, so its objects are naturally capable of responding to users' events.
It's a decision between UIView and CALayer. For the CALayer, I have done quite a bit of work on it and it looks quite ok except about the touch response that has to be added. Or should I use a UIView as subview instead (since it has build-in touch respond) ?
Hope that somebody knowledgable on this could help ...

In order to respond to user interaction, the best way is to use a UIView. You could probably get it to work without one, but I wouldn't recommend it.
As for integrating your existing layer with the UIView, I'd create a subclass of UIView and override its +layerClass method to return the Class of your custom CALayer. Alternatively, if you're not using a custom CALayer subclass (and there generally isn't a real need to create your own), you can do your custom drawing inside the UIView's -drawLayer:inContext: method.

Related

using a subclass of UITableViewCell in IB - Why is there a need to override drawRect:?

https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html#//apple_ref/doc/uid/TP40007451-CH7-SW12
In relation to subclassing UITableViewCell, the above link talks about the need to override drawRect: to explicitly draw the cells content.
But why is this necessary? Can we not just create a subclass of UITableViewCell in IB, add the required subviews in IB, create the required outlet connections and then set the values of these subviews programmatically.
Why is there a need to override drawRect:?
You're not required to override drawRect: any more than you are required to use the textField implementation methods for UIAlertView. Drawing the cell's content, however, can boost performance in some cases, particularly if you have multiple non-opaque layers and can draw them into one opaque cell, because the renderer doesn't have to composite and blend multiple times. By drawing into a single opaque layer, the hardware only has to blend right before it gets displayed on screen.
Note that if you don't experience lag or if you have animation in each cell themselves, then drawing will not help you.
I can't find in your link where it says you are supposed to subclass DrawRect method.
I don't think apple recommand it.
I have developped an entire app with a lot of tableControllers with custom tableViewCells, using nib files and never subclassing drawRect method.
I never noticed any problem, and my app passed successfully the app store review.

How to prevent drawings to a UIView context from dissappearing?

I'd like to create a simple fingerpainting feature in my app. Problem is any drawings I do to my UIView subclass view instance are erased after each drawRect call... How do you go about preserving your context drawings in your UIViews?
You have to add your drawings to your model and make sure your model is rendered, as appropriate, when the view is invalidated. You do not want to be drawing on the view directly without a model around to re-render it when necessary.
Jacob

iPhone need to get a CGContextRef context reference for a sub view

I'm using an IBoutlet to get a reference to a Sub-View I added to the main View in the interface builder but since this won't give me access to drawRect: I won't be able to get a context to draw on. Is there anyway I can still get the graphics context so I can draw on the sub view? How would I go about this?
You can't draw like that; you have to draw in response to a drawRect call, not at any time as some frameworks allow.
The correct way to do it is: create a UIView subclass in Xcode. Switch to Interface Builder, select your subview, and change its "Class Identity" (under "Tools > Identity Inspector") to the name of your new subclass.
Then in your subclass, you can implement drawRect.
Technically there is a means to for one object to become the drawing delegate of another via the view.layer.delegate route. One can construct a delegate to implement
(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
This gives you the ability to reuse drawing instructions should it become necessary. But it can be tedious to read and understand for another programmer. Most would avoid it unless it eliminates code duplication.
You should never be drawing in another view, not even a subview. The subview should draw itself, and it has access to its own graphics context. You cannot get access to another view's context; they are handled by the framework and are set up before calling -drawRect: for the appropriate view.

Signature Panel

My requirements are I need a panel where user can make signature. The concept is like when user touches the screen and move the pointer, it should be marked with continuous line.
Please gimme some idea how to implement this??
Subclass UIView and override the various UIResponder methods dealing with touch. Especially pay attention to touchesMoved:withEvent: - this is the method where you can get data about the previous/current points of the touch, and potentially add them to a set of points the touch has moved through. You can also override drawRect: in your custom UIView to draw a curve through all the points the touch has passed.
More info:
UIResponder reference
UIView reference

Do CALayers block Touch Events in underlying views?

I have an application with a view containing several subviews. The subviews did not implement any touchesbegins logic. The Superview implemented all touchesbegins logic and manipulated each subview respectively if it was touched (determined by hit testing).
I have since been converting my subviews to layers. My problem now is that if I touch a layer, the hosting view of the superlayer never gets the touchesbegins method called. However if I touch the background, the touchesbegin method fires.
I understood from documentation that layers cannot handle events, if this is so why would it block events to the hosting view?
Thanks for any help, can't get my head around this.
-Corey
I found the problem... I was releasing the sublayers I was creating using [CALayer layer]. Since I didn't have control of them, I shouldn't have been managing them.
CALayers should not block touch events. Is your userInteractionEnabled flag set in the hosting view (sounds like it is, if you're getting SOME touches)? Is it inside a UIScrollView, which may be doing its own touch-handling.
What class is your touchesBegan method in?
I was having a similiar problem because my touchesBegan method was in a UIView subclass.
After moving the method to a UIViewController subclass, my problem was fixed.
Try doing that.