How Can i Call
-(void)drawRect:(CGRect)rect
in https://github.com/stkim1/MTImageMapView/blob/master/MTImageMapView/MTImageMapView.m
From Another UiViewController Periodically With NSTimer
From the documentation:
Discussion
The default implementation of this method does nothing. Subclasses
that use technologies such as Core Graphics and UIKit to draw their
view’s content should override this method and implement their drawing
code there. You do not need to override this method if your view sets
its content in other ways. For example, you do not need to override
this method if your view just displays a background color or if your
view sets its content directly using the underlying layer object.
...
If you subclass UIView directly, your implementation of this method
does not need to call super. However, if you are subclassing a
different view class, you should call super at some point in your
implementation.
This method is called when a view is first displayed or when an event
occurs that invalidates a visible part of the view. You should never
call this method directly yourself. To invalidate part of your view,
and thus cause that portion to be redrawn, call the setNeedsDisplay or
setNeedsDisplayInRect: method instead.
YES i Found The solution i am calling a function with timer at the End of a drawrect function and calling setNeedsDisplay()in it
Related
CALayer seems to have almost everything required to add properties to a layer at runtime, without subclassing, using a delegate and/or the layer's actions property. However, one thing I have not figured out is how to trigger display updates when one of these dynamic properties changes in an animation.
I know how do this in a custom subclass of CALayer: simply define the properties in the subclass, mark them #dynamic, and override needsDisplayForKey: and return YES for the custom properties. Then display will be invoked during animations, which, by default, will even trigger a call to the layer delegate's drawLayer:inContent: method, if present (though it's of questionable usefulness, given that you've already got this subclass where you can implement drawInContext:). However, I am trying to see if this is possible without subclassing CALayer.
I can get as far as supporting updates outside of animations using only a layer delegate, by installing a CAAction in the layer's actions property, or implementing actionForLayer:forKey: in the layer delegate, and having that action send a setNeedsDisplay message to the layer. However, actionForKey: is apparently not called during an animation (makes sense, since it is used to trigger implicit animations), and there is no equivalent to needsDisplayForKey: in the layer delegate protocol, that I can see.
So, is there any way to tell CALayer to call display for custom properties besides the above? Or is it not possible to implement animatable custom layer properties in a layer delegate alone? It seems like Apple would prefer one to use delegation when possible, but without a way to refresh the layer contents during an animation, the delegate interface is incomplete. Any suggestions?
Let's call this UIView subclass - SomeClass. This SomeClass is a part of a static library. Some customer will use this library and will add instances of this SomeClass to the cells of his (customer's) table view.
I (SomeClass) need to determine when the SomeClass "enters" screen (will become visible), and when will "exit" screen (will become non-visible).
I can use didMoveToWindow: method and then check self.window for nil. BUT, there is a problem, SomeClass gets this event, before it is actually visible, because of cells "preparation" by table view concept. And I need to know for sure, it is 100% visible by some user.
One way to determine is by using scrollViewDidScroll:. Suppose SomeClass will get scroll view by using iteration on super views and will subscribe as a delegate to found scroll view. But he will be removed by some cell that will subscribe itself as a delegate to scroll view. So I need to invent here some solution for this. For example, in Android, there is possibility to add observer, in that case SomeClass is always a listener and is not overriding any other listener. There is many to one relation in Android, not like in iOS, one to one.
The other way, I can enable some timer in didMoveToWindow: when SomeClass becomes visible, that will check each X time, its frame. The timer will be disabled, when SomeClass will go from screen.
Probably there is a way to check at low level, without using scroll view and timer on some low-level redraw method. Is it possible?
So what is the best (will use less resources / good design) method?
You can use CGRectIntersectsRect to check if the cell's frame intersects with the frame of your custom view. Aside from that, didMoveToWindow is the method you are looking for.
If as you say the table view cell will always have SomeClass as a subview, then it would make more sense to use UITableViewDelegate tableView:willDisplayCell:forRowAtIndexPath:.
I found this in the Quartz 2D Programming Guide:
To draw to the screen in an iOS application, you set up a UIView object and implement its drawRect: method to perform drawing. The view’s drawRect: method is called when the view is visible onscreen and its contents need updating. Before calling your custom drawRect: method, the view object automatically configures its drawing environment so that your code can start drawing immediately. As part of this configuration, the UIView object creates a graphics context (a CGContextRef opaque type) for the current drawing environment. You obtain this graphics context in your drawRect: method by calling the UIKit function UIGraphicsGetCurrentContext.
Since I am having problems with invalid Context (because it's 0x00 when I go back to re-draw), I was wondering if I could get the current context in the beginning of -drawRect and somehow pass it to the methods I call from within -drawRect?
You can definitely pass CGContextRef to methods called from drawRect: as long as these methods do not save the reference for use outside the duration of the drawRect: call, your code should be fine. However, the context reference that you pass around would be equivalent to the context retrieved through UIGraphicsGetCurrentContext, so I doubt that there is much to gain by adding an extra parameter.
UIGraphicsGetCurrentContext can only be called from drawRect: method (or methods called from it) otherwise it will return nil.
You can use UIGraphicsGetCurrentContext from any method called from -drawRect. It's worth noting that you should not call -drawRect directly when you need to update your view; call -setNeedsDisplay instead.
If you want to use the UIKit drawing system with your own off-screen context, you can use UIGraphicsPushContext to set the current context.
In my experience, passing CGContextRef produces a memory leak that's pretty "fast."
I have several UITextViews in several ViewControllers. In the past, when I have a couple of instances of needing a custom drawing for a TextView or Label, etc I would just adjust the drawing in viewWillAppear inside the VC that owned the UI object. This time, I will be needed several instances to be customized.
Would it be more appropriate to just create a subclassed UITextView and include the drawing code in drawRect versus having the same drawing code spread around several VC's. I am mainly worried about performance. Code maintainability is a secondary concern though.
To be clear, this is what I would use in drawRect:
- (void)drawRect:(CGRect)rect {
self.layer.cornerRadius = 10;
self.clipsToBounds = YES;
}
So after further testing, initWithFrame doesn't get called, but initWithCoder does. I have also found that initWithCoder is called once and so is drawRect. In my use case (a StaticCellTableView with the UITextView in a cell, what would the difference be?
You can include those 2 lines in init or initWithCoder (In case it's a xib or storyboard) method of the subclassed UITextView.
Basically, this is just properties of the object - the don't need to run every time the UIView needs to refresh itself.
Create a ViewController baseclass, and then use that as the superclass for all your other VCs. You can then add this and other convenience methods to it and share the wealth so to speak.
In this particular case, putting it at the end of viewDidLoad would be a good place, as that is only messaged once, where viewWillAppear may be called multiple times. If you use viewdidLoad the code will be executed once.
I would not put those lines in the view's drawRect since that's called for every refresh. I'd recommend that you subclass UITextView and add those lines to the custom init method.
I have a few UIpickerView's that sends setNeedsDisplay to their parent view.
Is there any way to get the identity of the sender ?
Thanks
Shani
There is no way for you to get the sender of that method. There are a couple important things to note here: first, you shouldn't be overriding setNeedsDisplay at all, you should override drawRect: which will be called if the view needs to be redrawn. Second, I would suggest you use UIPickerView's delegate property, set it your parent view, and then do any processing you need to do in the pickerView:didSelectRow:inComponent: delegate method.