Search code examples
ios5uiviewxcode-storyboard

Moving iOS app to using Storyboards while retaining some views programmatically


I am trying to convert my existing project into using Storyboards, so that I can visually lay out my views. I still need to load some views into other views programmatically though.

(as a side note .. I used to program in Flash ActionScript, and am quite new to programming in iOS and have only taken a primer to Objective-C, so I have some tremendous "holes" that I am trying to work through).

My layout is something like this:

A calendar has a subview to create its cells - 'gridView'. I originally had this view created programmatically, which in turn added its own subviews for the calendar cells (the squares that show the date). I have added the gridView to the storyboard successfully and it does display the calendar cells (which are added programmatically by the gridView). I had successfully been able to display the correct dates onto the calendar, which I now have broken using storyboards and am trying to decide if I need to go back to creating the gridView programmatically, or if I can indeed do what I want to do in Storyboards.

So here is where I am stuck:

In my gridView I use draw rect to create all of the cell subviews:

// lay down the individual cells to build the calendar
    // 7 days across x 6 weeks down
    const CGSize gCellSize = {self.frame.size.width/7, (self.frame.size.height-20)/6};
    for(int w=0;w<6;w++) //6 weeks in the calendar
    {
        for(int d=0;d<7;d++) //7 days in a week
        {
            // ------------------ setting up the CELLVIEW ----------------------//
            CGRect calendarCellRect=CGRectMake(d*gCellSize.width,w*gCellSize.height+20, gCellSize.width, gCellSize.height);
            CalendarCellView *cellView=[[CalendarCellView alloc] initWithFrame:calendarCellRect];
            [self addSubview:cellView];
        }
    }

so here is my issue: When I created everything programmatically, the gridView was loaded as a subview to the parent view, and the cellViews were laid out just fine. After the gridView is loaded, the parent view would continue on with a method (displayDates - inside gridView) that loops through those subviews, and adds their appropriate date to each cellView.

but now that I have added the gridView to the storyboard, I need to make sure that its cell subviews are loaded before I can call the displayDates method.

-(void)displayDates:(NSArray *)selectedMonthDates previousMonthVisibleDates:(NSArray *)previousMonthDates followingMonthVisibleDates:(NSArray *)followingMonthVisibleDates
    {   
        int cellNum=0;
        NSArray *displayDates[]={previousMonthDates,selectedMonthDates,followingMonthVisibleDates};
        for (int i=0; i<3; i++)
        {
            for (NSDate *d in displayDates[i])
            {            
                CalendarCellView *cell=[self.subviews objectAtIndex:cellNum];
                [cell resetState]; //initialize all properties within the CellView

                cell.date=d; // set the cell's date property to be equal to the respective date collected from the displayDate array            
                cellNum++;
            }
        }
        [self setNeedsDisplay];
    }

So how do I make sure that the drawRect in gridView has added all of the subviews, before I come along and try to add the dates to those subviews?


Solution

  • The layout phase is done before the rendering phase. If you are creating subviews in drawRect you are already doing it wrong. All "last moment" layout should be done in -layoutSubviews: for an UIView subclass which you override.

    When adding to table view cell you should add your subviews to cell.contentView not to cell.view directly. See Table View Programming Guide paragraph A Closer Look at Table-View Cells for the anatomy of table view cell.

    Also, you should not rely on the order of subviews in the array. Instead you should tag your subviews (cellView.tag = d) since the order of subviews is not guaranteed in view hierarchy when loaded from nib or storyboard. You can get a hold of the subview by calling cell.contentView.viewWithTag:tag.

    And why not set the dates in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath which is the most common place to set values of UI elements in a table view cell.