views:

180

answers:

1

Summary

I'm repurposing Apple's Page Control project. In loadScrollViewWithPage:, the view controllers that I'm adding to the scroll view appear on screen without their initialized values, as if displayed directly from the nib.

Specifics

Here's the code that appears to be working when I step through it:

 CBFullScreenViewController *controller = [viewControllers objectAtIndex:page];

 if ((NSNull *)controller == [NSNull null]) {
  controller = [[CBFullScreenViewController alloc] init];

  // Populate the view from the corresponding CBImage object
  CBImage *imageObject = [imageArray objectAtIndex:page];
  BOOL bookmarked = [imageObject.bookmarked boolValue];
  controller.bookmarkButton.highlighted = bookmarked;
  NSString *subtitle = imageObject.subtitle;
  controller.closedSubtitleLabel.text = subtitle;
     // <-- snip...more initialization --> //
  controller.delegate = self;

  [viewControllers replaceObjectAtIndex:page withObject:controller];
  [controller release];
 }

// add the controller's view to the scroll view if (nil == controller.view.superview) { CGRect frame = scrollView.frame; frame.origin.x = frame.size.width * page; frame.origin.y = 0; controller.view.frame = frame; [scrollView addSubview:controller.view];//<< controller and subviews } // all have non-null, seemingly // valid values at this point

Here's the init method in CBFullScreenViewController:

- (id)init {
 if ((self = [super initWithNibName:@"CBFullScreenViewController" bundle:nil])) {
  self.cover = [[UIImageView alloc] init];
  self.homeButton = [[UIButton alloc] init];
  self.tabView = [[UIButton alloc] init];
  self.closedSubtitleLabel = [[UILabel alloc] init];
  self.openSubtitleLabel = [[UILabel alloc] init];
    // <-- snip...more initialization --> //
 }
 return self;
}

While troubleshooting this for the last 2 hours has helped me track down some unrelated memory leaks, I can't for the life of me figure out what's happening to the values I'm putting into my view!

Oh, it's probably worth mentioning that I've got @synthesize for each of my outlets, and they're all hooked up in IB. Screenshot here.

A: 

Hours later....

My solution

As noted above, I finally found a clue in that the sub-views' viewDidLoads weren't firing until after I'd done all my initialization on the buttons and whatnot, implying that the nib was overwriting all of my initialization.

One solution that worked was to make the scroll view a delegate of the subviews...

@interface CBScrollViewController : UIViewController
          <***CBFullScreenViewControllerDelegate***, UIScrollViewDelegate> {
...etc...

and then initialize everything by calling a function in the delegate from within the subview's viewDidLoad.

CBFullScreenViewController.h

@protocol CBFullScreenViewControllerDelegate
- (UIImage *)imageForFullScreenView:(CBFullScreenViewController *)controller;
@end

CBScrollViewController.m

- (UIImage *)imageForFullScreenView:(CBFullScreenViewController *)controller {
    NSUInteger page = controller.pageNumber;
    CBImage *image = [imageArray objectAtIndex:page];
    UIImage *pixels = [CBDataAccess pixelsForImage:image];
    return pixels;
}

An even better solution

In the end, though, the problem was architectural. The first way I implemented it, all of my controls were duplicated as each view was swiped into place, which was both ugly and wasteful.

The code above shows how I ended up having nothing in my subviews other than a UIImageView because all of the controls really only needed to be loaded once: floating motionless over the image. Loading a nib for a single, full-screen view is total overkill.

The better solution, then, is to use Interface Builder for the scroll view's more complex layout with the buttons and sliding info tab that I had, but leave Interface Builder out of it for the subviews, which can just as easily be loaded programmatically.

clozach