Question about MapView allocation


#1

Hi everybody,
I’m new in the forum and I’d like to start by thanking the authors and the users: these pages are a precious resource for anyone who’s walking his way through the manual pages.
I am struggling a bit with the new Xcode 4.2 as I decided to stick to the new version and iOS5, which implies different project templates and the use of ARC: still, it is doable…

Here is my question: I would have expect the MapKit object (referenced by the variable ‘worldView’ in the text) to be allocated and initialized in the bviewDidLoad method[/b] (for whom is coding in the ViewController - Xcode 4.2 -) or in application:didFinishLaunchingWithOptions: (for the ones who are writing in the AppDelegate file), as it happens for the locationManager. Something like:

[i] locationManager = [[CLLocationManager alloc]init];
[locationManager setDelegate:self];

[b]worldMap = [[MKMapView alloc]init];[/b]

[locationManager setDistanceFilter:kCLDistanceFilterNone];[/i]

If you try to allocate it as I did in the code above, the resulting map on the screen will always be centered on a fixed place regardless of the user location.
Without the memory allocation, the applications starts and locates the exact point of myIphone (I also discovered that it only works on the device, if I try the iPhone 5.0 simulator
it wouldn’t localize my position correctly).
Why are we avoiding to allocate the MapView instead of thinking along the line of the locationManager?
Thanks in advance


#2

Hi,

You have a choice when creating UI controls on a view or window to use Interface Builder or handwritten code.

In this app all the UI elements have been placed in the MainWindow.xib using Interface Builder.
Then a non-visual object (locationManager) has been created in the code.

What you are trying to do would work but there are a few things that Interface Builder has done for you in addition to just creating the MKMapView.

It has created the mapView and set it’s size.
worldView = [[MKMapView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];

Added this view to the window
[self.window addSubview:worldView];

In the right position
[self.window sendSubviewToBack:worldView];

and set the delegate
[worldView setDelegate:self];

and a whole bunch of other stuff depending on what settings you chose.

So if you remove the MapView from the xib and put this code in the appDelegate you should get the same results.
Please note I am not recommending this - just explaining how it works.

Conversely, you could define the CLLocationManager with an IBOutlet, drag an NSObject into the xib, change it’s class to CLLocationManager and wire it up to the appDelegate and then remove the alloc/init from the code.

So it’s really up to each developer to decide how they want to achieve the same thing. Some prefer Interface Builder as it’s a lot less code to write and easier to position controls. Others like the explicit control that you get by doing everything in code.

I would suggest sticking with how and where things are created in the book and then once you get to the end you’ll have a taste of both approaches to make your own decisions in your own apps.

Above all, be consistent to avoid maintenance problems later on and make sure you become familiar with the lifecycle of objects in nibs. You’ll often see people having problems referring to controls that haven’t yet been created by the xib at the point their code runs.

HTH
Gareth


#3

Hi Gareth,
thanks for your exhaustive answer.While searching for an explanation in my head, I totally overlooked the concept that UI objects created Interface Builder in the xib file, or the equivalent storyboard, are indeed already allocated by the program even id there is no corresponding visible code. Which explains the need to allocate the locationManager and not
the MapView, and also why an hardwritten allocation of the MapView following the one in the Interface Builder resulted in a new map not behaving as I would have expected.
Much now clearer, sir!