Do I have to implement mapView:regionWillChangeAnimated:on my MKMapview delegate? - iphone

Apple's docs tell you this method should be as lightweight as possible, what's a standard use here? Resetting the annotation pins?
Tells the delegate that the region
displayed by the map view is about to
change.
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated
Parameters
mapView
The map view whose visible region is
about to change.
animated
If YES, the change to the new region
will be animated. If NO, the change
will be made immediately.
This method is called whenever the
currently displayed map region
changes. During scrolling, this method
may be called many times to report
updates to the map position.
Therefore, your implementation of this
method should be as lightweight as
possible to avoid affecting scrolling
performance.

The problem with this delegate method is "During scrolling, this method may be called many times to report updates to the map position" (so you need IF/THEN or CASE/BREAK, etc to keep it "lightweight").
You don't NEED to use this method at all (not required), but if you do wish to incorporate some sort of functionality (such as removing worthless pins, etc), then example code to keep it lightweight would be:
- (void)mapView:(MKMapView *)mapView regionWillChangeAnimated:(BOOL)animated{
if(!animated){
//Instantaneous change, which means you probably did something code-wise, so you should have handled anything there, but you can do it here as well.
} else {
//User is most likely scrolling, so the best way to do things here is check if the new region is significantly (by whatever standard) away from the starting region
CLLocationDistance *distance = [mapView.centerCoordinate distanceFromLocation:originalCoordinate];
if(distance > 1000){
//The map region was shifted by 1000 meters
//Remove annotations outsides the view, or whatever
//Most likely, instead of checking for a distance change, you might want to check for a change relative to the view size
}
}
}

Related

Rotation - slowing it down using willAnimateSecondHalfOfRotationFromInterfaceOrientation

people, how do you actually slow down the orientation-rotation when using the "willAnimateSecondHalfOfRotationFromInterfaceOrientation:" method?
I currently have this:
-(void) willAnimateSecondHalfOfRotationFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
duration:(NSTimeInterval)duration {
[self positionViews];
}
And I understand that this "willAnimate2ndHalf..." method gets called automatically when the rotation does indeed happen - well where do I actually get to change its DURATION value?
If you want to change the overall timing of he app's rotation, it can't be done. willAnimateSecondHalfOfRotationFromInterfaceOrientation is meant for adding custom code, like setting custom coordinates, properties, things like that.

iOS: MKAnnotationViews are very slow to appear

I am adding 54 annotations to an MKMapView in a loop like this:
for (Item *item in items) {
[mapView addAnnotation:item];
}
I am logging when this completes and it never takes long, but there is a very long delay before the annotations appear on my map view. What is going on? How can I get the annotations to appear faster?
Update: the data set I am using is not small and I am holding it entirely in memory. I have noticed the occasional level 1 or 2 memory warning. Could this impact MKMapView performance?
There's nothing wrong with that code for adding annotations. The problem is probably somewhere else. Maybe you're getting the annotations from a web service. Maybe your annotation view objects are very large or complex.
If you want to try a different approach, use addAnnotations: to add all annotations at once, but I don't think it will make a difference.

Update AnnotationView after/during zoom

I need to change the centerOffset property of an AnnotationView when the zoomlevel changed. I don't want to remove and add the Annotations again.
So how can I access and update the AnnotationViews after zooming?
Any ideas on this?
Best Regards,
Christian
One solution would be to use these MKMapView methods :
- (NSSet *)annotationsInMapRect:(MKMapRect)mapRect // iOS4.2+ only!
to retrieve visible Annotations, then use :
- (MKAnnotationView *)viewForAnnotation:(id<MKAnnotation>)annotation;
To get the corresponding view (should never return nil if first function does it job correctly)
Then I guess changing centerOffset should do the job, (plus maybe some -[UIView setNeedsDisplay/Layout] to force a redraw)
Changing centerOffset depending on zoomLevel sounds strange, but I guess you have your reasons :)

Exactly what should happen in a CALayer's display/drawRect methods?

Which, if either, of these methods would be an appropriate place to:
Change the text of a CATextLayer
Load a different image into a CAImageLayer
Tell sublayers to update themselves
Dude I may be way drunk ... but there is NO drawRect method in CAlayers
I think you can use drawInContext: to actually (gulp) draw in to CALayers, but nobody is man enough to do that since WW2.
Regarding display, you don't need to call it, it basically updates what you set using .contents.
I just use .contents something like this ...
[self.view setLayer:rearLayer];
[self.view setWantsLayer:YES];
rearLayer.frame = CGRectMake(gameBlah,gameBlah, 1024,768);
// note that we are dealing there with the mysteries of rearLayer positioning;
// it is measured by the SUPER layer of the layer in question!
// (indeed much as frame for the view is, if you think about it ..)
rearLayer.contents = (id)loadMacStylePng(#"spaceShip");
Say one had the guts to write one's own drawInContext: ...
In that case, it gets called (or abstracted out ... or recalculated, or something) when you call displayAsNeeded. (I've never needed to call displayAsNeeded:, that's for sure.)

iPhone scrollView add elements dynamically with id

I want to populate a scrollView with quite a few different UI elements.
Therefore I thought I would write a method that remembers the current Position in the scrollView and just adds the element to the scrollView at the current Position.
Something like:
- (void)addUIElement:(id)element withWidth:(CGFloat)width andHeight:(CGFloat)height andYGap:(CGFloat)YGap {
element.frame = CGRectMake(currentScrollPos.x, (currentScrollPos.y + YGap), width, height);
[scrolly addSubview:element];
//And then set the current scroll position here
}
Unfortunately when I try to do access element.frame = ..., I get request for member in something not a structure or union. When I try to do [element frame] = ... Lvalue required as left operand of assignment.
Now, first of all I am not sure what's the best way to dynamically add objects to a scrollview. Maybe anyone has a better or easier approach.
Then on the other hand, I don't get why the above does not work?! Would I have to cast my element to the actual class? I thought I would not have to do so... Also then my method would not make that much sense anymore. Or at least would require some more steps...
This should work I think:
[element setFrame:...];
However if you work with different UI elements in your method may be you can make your elements parameter UIView* instead of id? This way your code will work for all UIView subclasses (which is what you actually need I suppose)
The difference is that "id" doesn't have any kind of reference to a frame. It could be anything. You want to instead do (UIView *)element in the method declaration, or alternatively in the call to element.frame, you would do ((UIView *)element).frame.
(And yeah, all things that you put on the screen are inheriting from UIView -- UIButton, UIImageView, etc.)