I'm trying to make a simple bar chart showing the relative durations of sequentially recorded activities, and I can't for the life of me get it to display properly. It's based on simple UIView
animations, and parts of it seem to work, namely the drop shadow under the bar. However, the bars themselves never appear.
I'm doubly flummoxed, because I modeled the code very closely on another bar chart within my app that DOES work. The only real difference is the driving data and the orientation of the bars.
Here's the code, followed by the console readout:
-(void) displayDayChart
{
NSTimeInterval timeFrame = -86400; // 24 hours for this test, selectable in real life
NSDate *dayStart = [NSDate dateWithTimeIntervalSinceNow:timeFrame];
NSDate *ratNow = [NSDate date];
int y = (self.chartView.frame.size.height) - 5;
NSLog(@"DayStart is %@",dayStart);
// Data source
// Predicate to retrieve activities that stopped after the beginning of the timeframe, plus the currently running one
actPredicate = [NSPredicate predicateWithFormat:@"(startTime >= %@ AND stopTime <= %@) OR ((startTime <= %@ AND stopTime >= %@) OR (startTime <= %@ AND stopTime == NULL))",dayStart,ratNow,dayStart,dayStart,ratNow];
// Fetch the activities
NSFetchedResultsController *dayActivityFRC = [TimedActivity MR_fetchAllSortedBy:@"startTime" ascending:NO withPredicate:actPredicate groupBy:nil delegate:nil];
// int taCount = [TimedActivity MR_countOfEntities];
// NSLog(@"total of TimedActivities is %d",taCount);
int grabbedActivities = dayActivityFRC.fetchedObjects.count;
NSLog(@"total of grabbedActivities is %d",grabbedActivities);
NSLog(@"Number of TimedActivities in dayActivityFRC is %d",dayActivityFRC.fetchedObjects.count);
DayChartBar *thisBar;
TimedActivity *thisItem;
for(int i=0; i<(dayActivityFRC.fetchedObjects.count); i++)
{
thisBar = [[DayChartBar alloc] initWithFrame:CGRectZero];
thisBar.tag = i+1;
[self.chartView addSubview:thisBar];
thisItem = [dayActivityFRC.fetchedObjects objectAtIndex:i];
// Increment vertical location of bar
y = y - 20;
// Calculate top (currently timing) activity's duration
if (thisItem.stopTime == nil)
{
NSNumber *n = ([NSNumber numberWithDouble: abs([thisItem.startTime timeIntervalSinceDate:[NSDate date]])]);
thisItem.duration = n;
}
// Calculate bottom activity's duration
if (thisItem.startTime < dayStart && thisItem.stopTime > dayStart)
{
NSNumber *n = ([NSNumber numberWithDouble: abs([thisItem.stopTime timeIntervalSinceDate:dayStart])]);
thisItem.duration = n;
// NSLog(@"%@ is the bottom item",thisItem.name);
}
// Calculate middle activities' duration
if (thisItem.startTime > dayStart && thisItem.stopTime < ratNow)
{
NSNumber *n = ([NSNumber numberWithDouble: abs([thisItem.stopTime timeIntervalSinceDate:thisItem.startTime])]);
thisItem.duration = n;
}
NSLog(@"Check loop %@",thisItem.name);
NSLog(@"startTime is %@",thisItem.startTime);
NSLog(@"stopTime is %@",thisItem.stopTime);
NSLog(@"duration is %@\n",thisItem.duration);
// Width of view = 280
// Calculate width of bar (proportionate to length of activity vs timeframe, relative to available space in chart view)
int w = ((280) * ([thisItem.duration doubleValue])) / (abs(timeFrame));
NSLog(@"w = %d",w);
// Make an animated bar of the appropriate color and size
[UIView animateWithDuration:.3
delay:.2
options: UIViewAnimationCurveEaseOut // Deprecated, but still works
animations:^
{
// Starting state
thisBar.frame = CGRectMake(20, y, 0, 15);
thisBar.backgroundColor = [UIColor blackColor];
// End state
thisBar.frame = CGRectMake(20, y, w, 15);
NSLog(@"thisBar.frame is %@",NSStringFromCGRect (thisBar.frame));
thisBar.backgroundColor = thisItem.color;
thisBar.layer.shadowColor = [[UIColor blackColor] CGColor];
thisBar.layer.shadowOpacity = 0.7;
thisBar.layer.shadowRadius = 4.0;
thisBar.layer.shadowOffset = CGSizeMake(5.0f, 5.0f);
thisBar.layer.shadowPath = [UIBezierPath bezierPathWithRect:thisBar.bounds].CGPath;
NSLog(@"Bar created!");
}
completion:^(BOOL finished)
{
// Reserved for creating a name label at the end of each bar
NSLog(@"Bar completed!");
}];
}
}
And the Console readout:
2014-06-20 11:05:17.910 WMDGx[46607:a0b] Number of activities is 2
2014-06-20 11:05:22.793 WMDGx[46607:a0b] DayStart is 2014-06-19 18:05:22 +0000
2014-06-20 11:05:22.794 WMDGx[46607:a0b] total of grabbedActivities is 8
2014-06-20 11:05:22.795 WMDGx[46607:a0b] Number of TimedActivities in dayActivityFRC is 8
2014-06-20 11:05:22.796 WMDGx[46607:a0b] Check loop Dusting
2014-06-20 11:05:22.796 WMDGx[46607:a0b] startTime is 2014-06-20 17:29:04 +0000
2014-06-20 11:05:22.797 WMDGx[46607:a0b] stopTime is (null)
2014-06-20 11:05:22.797 WMDGx[46607:a0b] duration is 0
2014-06-20 11:05:22.798 WMDGx[46607:a0b] w = 0
2014-06-20 11:05:22.798 WMDGx[46607:a0b] thisBar.frame is {{20, 261}, {0, 15}}
2014-06-20 11:05:22.799 WMDGx[46607:a0b] Bar created!
2014-06-20 11:05:22.800 WMDGx[46607:a0b] Check loop Test 1
2014-06-20 11:05:22.800 WMDGx[46607:a0b] startTime is 2014-06-20 17:19:22 +0000
2014-06-20 11:05:22.801 WMDGx[46607:a0b] stopTime is 2014-06-20 17:29:04 +0000
2014-06-20 11:05:22.801 WMDGx[46607:a0b] duration is 581
2014-06-20 11:05:22.802 WMDGx[46607:a0b] w = 1
2014-06-20 11:05:22.803 WMDGx[46607:a0b] thisBar.frame is {{20, 241}, {1, 15}}
2014-06-20 11:05:22.803 WMDGx[46607:a0b] Bar created!
2014-06-20 11:05:22.804 WMDGx[46607:a0b] Check loop Dusting
2014-06-20 11:05:22.804 WMDGx[46607:a0b] startTime is 2014-06-20 16:52:10 +0000
2014-06-20 11:05:22.805 WMDGx[46607:a0b] stopTime is 2014-06-20 17:19:22 +0000
2014-06-20 11:05:22.805 WMDGx[46607:a0b] duration is 1632
2014-06-20 11:05:22.806 WMDGx[46607:a0b] w = 5
2014-06-20 11:05:22.808 WMDGx[46607:a0b] thisBar.frame is {{20, 221}, {5, 15}}
2014-06-20 11:05:22.809 WMDGx[46607:a0b] Bar created!
2014-06-20 11:05:22.810 WMDGx[46607:a0b] Check loop Test 1
2014-06-20 11:05:22.811 WMDGx[46607:a0b] startTime is 2014-06-20 16:52:04 +0000
2014-06-20 11:05:22.811 WMDGx[46607:a0b] stopTime is 2014-06-20 16:52:10 +0000
2014-06-20 11:05:22.812 WMDGx[46607:a0b] duration is 6
2014-06-20 11:05:22.812 WMDGx[46607:a0b] w = 0
2014-06-20 11:05:22.813 WMDGx[46607:a0b] thisBar.frame is {{20, 201}, {0, 15}}
2014-06-20 11:05:22.813 WMDGx[46607:a0b] Bar created!
2014-06-20 11:05:22.814 WMDGx[46607:a0b] Check loop Timer Sleeping
2014-06-20 11:05:22.814 WMDGx[46607:a0b] startTime is 2014-06-20 16:29:06 +0000
2014-06-20 11:05:22.816 WMDGx[46607:a0b] stopTime is 2014-06-20 16:52:04 +0000
2014-06-20 11:05:22.816 WMDGx[46607:a0b] duration is 1378
2014-06-20 11:05:22.817 WMDGx[46607:a0b] w = 4
2014-06-20 11:05:22.818 WMDGx[46607:a0b] thisBar.frame is {{20, 181}, {4, 15}}
2014-06-20 11:05:22.818 WMDGx[46607:a0b] Bar created!
2014-06-20 11:05:22.820 WMDGx[46607:a0b] Check loop Dusting
2014-06-20 11:05:22.821 WMDGx[46607:a0b] startTime is 2014-06-20 16:28:53 +0000
2014-06-20 11:05:22.821 WMDGx[46607:a0b] stopTime is 2014-06-20 16:29:06 +0000
2014-06-20 11:05:22.822 WMDGx[46607:a0b] duration is 12
2014-06-20 11:05:22.823 WMDGx[46607:a0b] w = 0
2014-06-20 11:05:22.824 WMDGx[46607:a0b] thisBar.frame is {{20, 161}, {0, 15}}
2014-06-20 11:05:22.825 WMDGx[46607:a0b] Bar created!
2014-06-20 11:05:22.826 WMDGx[46607:a0b] Check loop Test 1
2014-06-20 11:05:22.827 WMDGx[46607:a0b] startTime is 2014-06-20 16:28:38 +0000
2014-06-20 11:05:22.827 WMDGx[46607:a0b] stopTime is 2014-06-20 16:28:53 +0000
2014-06-20 11:05:22.827 WMDGx[46607:a0b] duration is 14
2014-06-20 11:05:22.828 WMDGx[46607:a0b] w = 0
2014-06-20 11:05:22.828 WMDGx[46607:a0b] thisBar.frame is {{20, 141}, {0, 15}}
2014-06-20 11:05:22.829 WMDGx[46607:a0b] Bar created!
2014-06-20 11:05:22.829 WMDGx[46607:a0b] Check loop Timer Sleeping
2014-06-20 11:05:22.829 WMDGx[46607:a0b] startTime is 2014-06-20 16:25:35 +0000
2014-06-20 11:05:22.830 WMDGx[46607:a0b] stopTime is 2014-06-20 16:28:38 +0000
2014-06-20 11:05:22.831 WMDGx[46607:a0b] duration is 183
2014-06-20 11:05:22.832 WMDGx[46607:a0b] w = 0
2014-06-20 11:05:22.834 WMDGx[46607:a0b] thisBar.frame is {{20, 121}, {0, 15}}
2014-06-20 11:05:22.834 WMDGx[46607:a0b] Bar created!
2014-06-20 11:05:23.348 WMDGx[46607:a0b] Bar completed!
2014-06-20 11:05:23.350 WMDGx[46607:a0b] Bar completed!
2014-06-20 11:05:23.351 WMDGx[46607:a0b] Bar completed!
2014-06-20 11:05:23.352 WMDGx[46607:a0b] Bar completed!
2014-06-20 11:05:23.352 WMDGx[46607:a0b] Bar completed!
2014-06-20 11:05:23.353 WMDGx[46607:a0b] Bar completed!
2014-06-20 11:05:23.354 WMDGx[46607:a0b] Bar completed!
2014-06-20 11:05:23.355 WMDGx[46607:a0b] Bar completed!
I hope this is just a dumbass case of not seeing the forest for the trees, but I've been beating my brains out for 3 days before bringing it to SO. I know it's not a proofreading site.
Here's a screenshot showing the drop shadows (and the absence of the bars themselves). The drop shadows appear to be in the right location and to be about the correct size based on the data:
**Edit*************
Following the comments by rdelmar and @gro below, I changed the line:
thisBar.backgroundColor = thisItem.color;
to:
thisBar.backgroundColor = [UIColor redColor];
Which produced this screenshot:
So, believing the problem to have been identified, I went back and changed this:
thisBar = [[DayChartBar alloc] initWithFrame:CGRectZero];
thisBar.tag = i+1;
[self.chartView addSubview:thisBar];
thisItem = [dayActivityFRC.fetchedObjects objectAtIndex:i];
to this
thisBar = [[DayChartBar alloc] initWithFrame:CGRectZero];
thisBar.tag = i+1;
[self.chartView addSubview:thisBar];
thisItem = [dayActivityFRC.fetchedObjects objectAtIndex:i];
thisBar.endColor = thisItem.color;
and this (in the animation block):
thisBar.backgroundColor = thisItem.color;
to this:
thisBar.backgroundColor = thisBar.endColor;
And now the bars have disappeared once again.
**Second edit*****************
I've had to do quite a bit of backtracking, but now the bars are displaying, albeit a bit strangely. The problem (the primary one at least) was that the colors assigned to each item through it's associated category, which is then passed on to the TimedActivity, which are represented by the bars. Yeah, I know, kinda convoluted. I need to look into cleaning it up.
In any case, this is what it looks like now. As I said, the behavior is a little weird--for example, the top bar only has a drop shadow and no bar, but at least I'm seeing some colored bars. However, the drop shadows, inexplicably, are being created before the bars themselves. Or so it would appear.