Question

I have a small problem with ARC and dealloc of the BaseViewController class being called after the instantiation inside the loop and I don't know why. What I'm trying to do is basically store all the base view controllers on an array.

@interface CategoriesContainerViewController ()
  @property (nonatomic, strong) IBOutlet UIScrollView* scrollView;
  @property (nonatomic, strong) NSMutableArray* categoriesViews;
@end

- (void)viewDidLoad {

  [super viewDidLoad];

  // Get the categories from a plist
  NSString* path = [[NSBundle mainBundle] pathForResource:@"categories" ofType:@"plist"];
  NSDictionary* dict = [[NSDictionary alloc] initWithContentsOfFile:path];
  NSMutableArray* categories = [dict objectForKey:@"Categories"];
  NSLog(@"%i", [categories count]);

  // Setup the scrollview
  _scrollView.delegate = self;
  _scrollView.directionalLockEnabled = YES;
  _scrollView.alwaysBounceVertical = YES;
  _scrollView.scrollEnabled = YES;

  CGRect screenRect = [[UIScreen mainScreen] bounds];

  // Loop through the categories and create a BaseViewController for each one and
  // store it in an array
  for (int i = 0; i < [categories count]; i++) {

    BaseViewController* categoryView = [[BaseViewController alloc]
                                        initWithCategory:[categories objectAtIndex:i]];

    CGRect frame = categoryView.view.frame;
    frame.origin.y = screenRect.size.height * i;
    categoryView.view.frame = frame;

    [_scrollView addSubview:categoryView.view];
    [_categoriesViews addObject:categoryView];
  }

}
Was it helpful?

Solution

You are committing a common beginner mistake by keeping a reference to a view controller's view, but not the view controller itself.

You create a BaseViewController object in a local variable categoryView. That's a strong reference, so the object is kept around. Then the loop repeats, and you create a new BaseViewController, replacing the old value in categoryView. When you do that, there are no longer any strong references to the previous BaseViewController that was in categoryView, so it gets deallocated.

If you want the BaseViewController to stick around, you need to keep a strong reference to it somewhere.

In addition to that, you are breaking another rule of iOS development. You should never put one view controller's view(s) inside another view controller's unless you use the parent/child view controller support that was added in iOS 5 and extended in iOS 6. The docs say do NOT do that.

Mixing views from multiple view controllers on the screen will cause you no end of problems. There is tons of housekeeping you have to do in order to make it work, and not all of that housekeeping is documented. Its possible, but it will take you many weeks to iron out the bugs, if you ever able to. Plus, since you are doing something that Apple expressly says not to do, the burden is on you to make it work correctly, and there is a substantial risk that a new iOS release will break your app.

OTHER TIPS

Initialize BaseViewController above for loop and then store the array value inside the object of BaseViewController. Because every time it is allocating and initializing. So setting the previous object to nil. Hence the issue causes to be deallocated.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top