Resizing Custom MKAnnotationView According to MapKit Zoom Level - iphone

Here is the situation:
I am displaying images on the map by using custom annotations. Everything works fine but I would like to improve it visually by resizing the AnnotationView so that it shrinks as the map is zoomed out. I want to do this because, obviously, more annotations fill up the screen and need to be shrunk so that they don't overlap each other too much and the user can see more annotations. (Of course, I would like to enlarge AnnotationViews when the map is zoomed in again).
I have achieved this by removing all annotations from the map and adding them back again, whenever regionDidChangeAnimated is called. However, these images are loaded from the internet, so downloading the images again (since the annotations have been removed) doesn't seem to make sense.
I hope I have explained the situation well, and hope to contribute to SO in the future.
Thanks in advance.
P.S. I'm developing with iOS 4.0

Since you are using iOS 4.0 I would suggest using a class that conforms to the MKOverlay protocol instead of MKAnnotationView. Overlays zoom with the map and will scale appropriately. You can probably use 1 overlay to handle all your annotations. Check out the HazardMap demo Apple provided in the 2010 WWDC talks on http://developer.apple.com
Alternatively, you could use something like the k nearest neighbors algorithm to group annotations per zoom scale. However, that can be kind of slow if you have a lot of annotations. I tried it once with several thousand annotations and did not like the performance hit that was incurred. I think < 1000 annotations might have decent performance with this method though.

It sounds like you're already on the right path and that the only real problem is the downloading of the images. Is there any particular reason you can't cache them by writing them to the documents directory (or the cache directory if you want them to go way when the app quits) when you receive them and look there first before displaying them?

Related

Rendering a preview of a UIView in another UIView

I have a very intriguing obstacle to overcome. I am trying to display the live contents of a UIView in another, separate UIView.
What I am trying to accomplish is very similar to Mission Control in Mac OS X. In Mission Control, there are large views in the center, displaying the desktop or an application. Above that, there are small views that can be reorganized. These small views display a live preview of their corresponding app. The preview is instant, and the framerate is exact. Ultimately, I am trying to recreate this effect, as cheaply as possible.
I have tried many possible solutions, and the one shown here is as close as I have gotten. It works, however the - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx method isn't called on every change. My solution was to call [cloneView setNeedsDisplay] using a CADisplayLink, so it is called on every screen refresh. It is very near my goal, but the framerate is extremely low. I think that [CALayer renderInContext:] is much too slow.
If it is possible to have two CALayers render the same source, that would be golden. However, I am not sure how to approach this. Luckily, this is simply a concept app and isn't destined for the App Store, so I can make use of the private APIs. I have looked into IOSurface and Quartz contexts, but I haven't been able to solve this puzzle so far. Any input would be greatly appreciated!
iOS and OSX are actually mostly the same underneath at the lowest level. (However, when you get higher up the stack iOS is actually largely more advanced than OSX as it is newer and had a fresh start)
However, in this case they both use the same thing (I believe). You'll notice something about Mission Control. It isolates "windows" rather than views. On iOS each UIWindow has a ".contentID" property and CALayerHost can use to make the render server share the render context between the 2 of them (2 layers that is).
So my advice is to make your views separate UIWindows and get native mirroring for free-(ish). (In my experience the CALayerHost takes over the target layers place with the render server and so if both the CALayerHost and the window are visible the window won't be anymore, only the layer host will be (which the way they are used on OSX and iOS isn't a problem).)
So if you are after true mirroring, 2 copies of it, you'll need to resort to the sort of thing you were thinking about.
1 Option for this is to create a UIView subclass that uses
https://github.com/yyfrankyy/iOS5.1-Framework-Headers/blob/master/UIKit.framework/UIView-Rendering.h#L12
this UIView private method to get an IOSurface for a target view and then using a CADisplayLink once per second get and draw the surface.
Another option which may work (I'm not sure as I don't know your setup or desired effect) is possibly just to use a CAReplicatorLayer which displays a mirror of a CALayer using the same backing store (very fast and efficient + public stable API).
Sorry I couldn't give you a fixed, "this is the answer reply", but hopefully I've given you enough ideas and possibilities to get started.
I've also included some links to things you might find useful to read.
What's the magic behind CAReplicatorLayer?
http://aptogo.co.uk/2011/08/no-fuss-reflections/
http://iphonedevwiki.net/index.php/SBAppContextHostManager
http://iphonedevwiki.net/index.php/SBAppContextHostView
http://iphonedevwiki.net/index.php/CALayerHost
http://iky1e.tumblr.com/post/33109276151/recreating-remote-views-ios5
http://iky1e.tumblr.com/post/14886675036/current-projects-understanding-ios-app-rendering

Optimizing Performance on iPhone

I released the first beta version of my iPhone app on TestFlightApp today. Everything is going really well until I notice that the responsiveness of the application is pretty cruddy. Certainly doesn't have a "nice" native feel that I'm going for.
I've been particularly fastidious concerning my memory allocation/deallocation, so I don't think this is the issue. Basically, I don't know where to turn to next in order to improve the performance of my app.
Here's where I think some of my slowdown can be attributed to:
Using UIAppearance to customize the looks of most (if not all) UI elements. I use a brand new font, lots of CAGradientLayers, and lots of edits to CALayer in order to draw nice Shadows.
Grouped UITableViewCells that display pictures of a map and itemized lists.
UITableViewCells whose layouts are updated every time I call layoutSubviews.
UITableViewCells with customized heights. For each call of heightForRowAtIndexPath, I need to reconstruct and re-layout the view, returning the exact height each time.
Because I programmatically created views, controllers with longer viewDidLoad calls tend to load slower. What code can I offset in the init call?
Does anyone have any hints or tips for dealing with these problems? Or perhaps people have stories about how they dealt with a slowdown in performance when they released their first app?
My answer won't address all of your points, but here are a couple:
1) Make sure you are using Shadow Paths. Paths are much, much more performant.
2) Are you using transparency or corner rounding? If so, try and reduce transparency as much as possible and do not round corners using CALayer cornerRadius. Instead, use a clipping mask in the drawRect of the view that needs to be rounded.
4) Perhaps you can cache the height in an array and not have to repeat the calculation, each and every time. This may/may not scale well depending on the potential number of items, but may be acceptable depending on the use case.
5) Are there views you can reuse? For example, when I have a custom selection view on a UITableViewCell, I only create a single instance held by the controller and reference it in all the cells.
Did you run Instruments (or other profiling methodology) to determine where you app is spending most of it's time. It would be a good idea to do this before optimizing the wrong thing.

Creating a tableview in the form of a 'film strip'

I am developing an RSS-reader-type application. I am toying with the possibility of using a normal TableView application but showing the articles as a film-strip. I am mainly thinking for an iPad application (but possible it works on the smaller iPhone as well).
The idea is to have the cells passing/scrolling across the screen using swipe touches (but horizontal, and not vertical as with the normal TableView). They will be some-kind of miniatures of the full article, and when tapped (or with multi-touch zoom to have better control) can be enlarged to read. Then can then just be be moved on as soon as the user has seen enough of it.
Does anybody know if there is an easy way of accomplishing something like that?
The most obvious solution that springs to mind would be to use a UIScrollView, as this will provide the inertial effects, etc. for free - all you'd have to do it populate it with the relevant sub-views. (UITableView's actually use a UIScrollView.)
For more information and sample code, see Apple's UIScrollView docs.
If you want horizontal scrolling, take a look at Jeremy Tregunna’s JScrollingRow. It’s open source under a public domain licence.

iPhone MKMapKit Image Overlay

How can an image overlay be applied to a MKMapView? Basically, when you zoom in a specific location, I want an image to appear on top of the map that gives a more detailed view of the location.
I've had a look around and found different types of methods to use. I had a working example for an older SDK using the DrawMapRect function but this no longer seems to work on 4.2.
This is a good place to start...
http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKOverlayView_class/Reference/Reference.html
I was looking for polygon sample code though.
#omniscian: If you have solved it you should post something helpful for others. This page has a high google rank.

UIPickerView that scrolls horizontally on the iPhone?

I'm taking a look at this widget, and it appears to be a UIPickerView, however I haven't seen anything provided by the iPhone SDK API that allows for horizontal scrolling only. Mostly it's all done vertically. Also there appears to be a custom graphic around this picker, so it might not be that either.
I'm curious if anyone is able to determine if this is indeed a UIPickerView or perhaps a hacked up UIScrollView? The widget is handy -- and I like its use. I found it in some random groceries app in the app store.
Here is the screenshot:
Thanks all.
I'd definitely use iCarousel library:
https://github.com/nicklockwood/iCarousel
The library is really well documented, the code is clean and maintained.
That is totally custom. You could indeed do something of the sort overlaying an UIImageView and an UIScrollView. I'd guess it's a 100% custom. As with all programming, there are many ways to do any single thing.
As I recently posted in response to this question, a class for an iOS horizontal picker control (STHorizontalPicker) has just been posted on GitHub. It's nowhere near as sophisticated as UIPickerView, but it provides the basic functionality for picking numeric values and the underlying foundation is probably a good starting point for adding more sophisticated functionality (it's a UIScrollView containing a UIView with multiple CATextLayers for the markers).
It was designed to be used in UITableCellViews and currently looks like this:
This website has source code for a picker that is aligned horizontally without subclassing it.
That definitely looks like a custom component. I'd suggest getting the .app file off your iPhone, opening up the bundle, and looking to see if there's a xib file for that interface. You may get lucky and find the component sitting in there. My guess is that it's a subclass of UIScrollView, but of course there's no way I could be sure of that without personally knowing the developer or the codebase.
You will recognize pickers by their giant screen-gobbling footprint :-) This is most likely a horizontal UIScrollView with a series of fixed-width labels (or images). The tricky bit is to have the bezel on top with a transparent center pass touches back to the underlying scroll view. Or you can take the easy way out and overlay four image strips (for each edge) and leave the middle open so touch events go directly to the scroller.
It's a custom control, but it's really not that hard to build.