Subtitle: locating the origin of a button
I have completed the map challenge of Chapter 7. I create the map view controller in the app delegate after creating the other two controllers, following the pattern. Then in the map view controller’s -loadView method, I create the map view programmatically, following the pattern of -loadView in HypnosisViewController.
Now, I want to add an info button that brings up an action sheet with four buttons to let the user select the map type. Actually, I have done just that; works great! But I have used hard-coded values to locate the button, which is a bad idea for long term compatibility and portability.
MKMapView *mv = [[MKMapView alloc] initWithFrame:CGRectZero];
mv.delegate = self;
My first intention was to set up the info button at the bottom right of the map view,
just above the tab bar. But with the frame of the map view set to CGRectZero, locating the button
becomes a challenge. When -loadView is invoked, the map view controller creates the map
view, but the view is not yet added to the window’s view, so mv.window returns nil and
window.bounds is also unavailable.
My second approach was to query the tab bar for its bounds and work from there. The tab bar
claims the whole window within its bounds.
So now, I will query the tab bar for the window, get the window’s bounds, and either place the button
with hard coded offsets
// set up map options info button
// first try: calculate button origin from mv.bounds or from the window’s bounds
CGRect mvBounds = mv.bounds; // returns CGRectZero
UIWindow *mvWindow = mv.window; // returns nil
CGRect windowBounds = mvWindow.bounds; // messages to nil are ignored
// try getting the bounds of the tab bar and calculating the button origin from
// the tab bar bounds
UIViewController *tbvc = self.parentViewController;
UIView *tb = tbvc.view;
CGRect tbBounds = tb.bounds; // tab bar claims whole window within its bounds (0.0, 0.0, 768.0, 1024.0)
CGRect screenRect = [UIScreen mainScreen].bounds; // also returns 0.0, 0.0, 768.0, 1024.0
// so get the window, use window.bounds and assume the height of either the status bar
// or the tab bar
UIWindow *window = tb.window;
CGRect wb = window.bounds;
buttonOrigin.x = wb.size.width - 40.0; // 40 units from right side of screen
buttonOrigin.y = wb.size.height - 100.0; // ? units above top of tab bar
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
CGRect buttonFrame = infoButton.frame;
buttonFrame.origin = buttonOrigin;
infoButton.frame = buttonFrame;
What is the correct way to programmatically query the OS regarding the size of existing objects so I can place the button relative to these objects?
Thanks for the help.
BTW, at the time I started the challenge, I saw only one view and chose the programmatic route. Now, I can see how using Interface Builder might make this easier. But I still would like to be able to do it either way.