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?
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.