Line Chart - Display xAxis at bottom - ios-charts

I've looked everywhere and tried various approaches and cannot figure this out.
How do I position the xAxis at the bottom of the line chart?
In viewDidLoad:
[self initChartProperties];
[self updateChartData:5];
initChartProperties:
- (void)initChartProperties2 {
_chartView.delegate = self;
_chartView.descriptionText = #"";
_chartView.noDataTextDescription = #"You need to provide data for the chart.";
_chartView.dragEnabled = YES;
_chartView.pinchZoomEnabled = YES;
_chartView.legend.enabled = NO;
[_chartView setScaleEnabled:YES];
_chartView.leftAxis.customAxisMax = 21;
_chartView.leftAxis.customAxisMin = 0;
_chartView.leftAxis.drawZeroLineEnabled = NO;
_chartView.leftAxis.enabled = YES;
_chartView.xAxis.axisLineWidth = 2.0f;
_chartView.xAxis.drawAxisLineEnabled = YES;
_chartView.rightAxis.enabled = NO;
[_chartView.viewPortHandler setMaximumScaleY: 2.f];
[_chartView.viewPortHandler setMaximumScaleX: 2.f];
}
updateChartData:
- (void)updateChartData:(int)count {
NSMutableArray *xVals = [[NSMutableArray alloc] init];
NSMutableArray *yVals = [[NSMutableArray alloc] init];
for (int i = 0; i < count; i++) {
[xVals addObject:[#(i) stringValue]];
}
for (int i = 0; i < count; i++) {
[yVals addObject:[[ChartDataEntry alloc] initWithValue:i xIndex:i]];
}
LineChartDataSet *set1 = [[LineChartDataSet alloc] initWithYVals:yVals label:#""];
set1.lineWidth = 1.0;
set1.circleRadius = 0.0;
set1.drawCircleHoleEnabled = NO;
set1.valueFont = [UIFont fontWithName:#"HelveticaNeue-Light" size:9.0f];
NSMutableArray *dataSets = [[NSMutableArray alloc] init];
[dataSets addObject:set1];
LineChartData *data = [[LineChartData alloc] initWithXVals:xVals dataSets:dataSets];
_chartView.data = data;
}
Result:
line graph
I just want the xAxis values to be rendered at the bottom of the graph, not the top.
Sorry for the seemingly simple question.
Appreciate any help.

Nevermind - finally figured it out
_chartView.xAxis.labelPosition = XAxisLabelPositionBottom;

In the most recent version (currently 3.0) you can do it with
_chartView.xAxis.labelPosition = XAxis.LabelPosition.bottom

Related

Accurately and seamlessly splitting text into two UILabels

I'm trying to create a "wrapping" like effect for text around an image that has set dimensions.
___________
........|
........| image
label.1.|
........|___________
....................
.......label.2......
....................
....................
Here is the method im using right now:
- (NSArray *)splitString:(NSString*)str maxCharacters:(NSInteger)maxLength { //this will split the string to add to two UILabels
NSMutableArray *tempArray = [NSMutableArray arrayWithCapacity:1];
NSArray *wordArray = [str componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSInteger numberOfWords = [wordArray count];
NSInteger index = 0;
NSInteger lengthOfNextWord = 0;
while (index < numberOfWords) {
NSMutableString *line = [NSMutableString stringWithCapacity:1];
while ((([line length] + lengthOfNextWord + 1) <= maxLength) && (index < numberOfWords)) {
lengthOfNextWord = [[wordArray objectAtIndex:index] length];
[line appendString:[wordArray objectAtIndex:index]];
index++;
if (index < numberOfWords) {
[line appendString:#" "];
}
}
[tempArray addObject:line];
}
return tempArray;
}
I give it the maxCharacters value of where I want to split the text, which is the max height of the first UILabel. This method is essentially what I want, but sometimes the last line of the first UILabel is "higher" than others leaving a gap between the first UILabel and the second UILabel.
Here is how I use the method:
NSArray *splitStringArray = [self splitString:eventRecord.summary maxCharacters:280];
UILabel *firstSumValue = [[UILabel alloc] init];
NSString *firstSumString = [splitStringArray objectAtIndex:0];
CGSize maxFirstSumSize = CGSizeMake(185.0,150.0);
UIFont *firstSumFont = [UIFont fontWithName:#"HelveticaNeue-Bold" size:12];
CGSize firstSumStringSize = [firstSumString sizeWithFont:firstSumFont
constrainedToSize:maxFirstSumSize
lineBreakMode:firstSumValue.lineBreakMode];
CGRect firstSumFrame = CGRectMake(10.0, presentedValue.frame.origin.y + presentedValue.frame.size.height, 185.0, firstSumStringSize.height);
firstSumValue.frame = firstSumFrame;
firstSumValue.font = [UIFont fontWithName:#"HelveticaNeue" size:12];
firstSumValue.lineBreakMode = UILineBreakModeWordWrap;
firstSumValue.numberOfLines = 0 ;
[self.mainScrollView addSubview:firstSumValue];
firstSumValue.text = [splitStringArray objectAtIndex:0];
UILabel *secondSumValue = [[UILabel alloc] init];
NSInteger isSecond = 0; //no
if([splitStringArray count] > 1){
isSecond = 1; //yes
NSString *secondSumString = [splitStringArray objectAtIndex:1];
CGSize maxSecondSumSize = CGSizeMake(310.0,9999.0);
UIFont *secondSumFont = [UIFont fontWithName:#"HelveticaNeue-Bold" size:12];
CGSize secondSumStringSize = [secondSumString sizeWithFont:secondSumFont
constrainedToSize:maxSecondSumSize
lineBreakMode:secondSumValue.lineBreakMode];
CGRect secondSumFrame = CGRectMake(10.0, firstSumValue.frame.origin.y + firstSumValue.frame.size.height, 310.0, secondSumStringSize.height);
secondSumValue.frame = secondSumFrame;
secondSumValue.font = [UIFont fontWithName:#"HelveticaNeue" size:12];
secondSumValue.lineBreakMode = UILineBreakModeWordWrap;
secondSumValue.numberOfLines = 0 ;
[self.mainScrollView addSubview:secondSumValue];
secondSumValue.text = [splitStringArray objectAtIndex:1];
}
How do I keep everything consistent and aligned properly. Perhaps, there is a better method one could recommend. Not core text because it's out of my scope of knowledge.
Consider using a UIWebView instead, with the layout defined in a local HTML file. It can save you a lot of headache rather than trying to deal with complex layouts by hand.

Problems with legend in Core-Plot (pieChart)

I have a problem drawing the legend of a pieChart with Core-Plot, because the name of each element of the chart in the legend is always the identifier of the CPTPieChart. Can someone help me? Thanks.
This is the source code:
-(void)constructPieChart {
// Create pieChart from theme
//[pieGraph applyTheme:theme];
pieChartView.hostedGraph = pieGraph;
pieGraph.plotAreaFrame.masksToBorder = YES;
pieGraph.paddingLeft = 0;
pieGraph.paddingTop = 20.0;
pieGraph.paddingRight = 0;
pieGraph.paddingBottom = 60.0;
pieGraph.axisSet = nil;
// Prepare a radial overlay gradient for shading/gloss
CPTGradient *overlayGradient = [[[CPTGradient alloc] init] autorelease];
overlayGradient.gradientType = CPTGradientTypeRadial;
overlayGradient = [overlayGradient addColorStop:[[CPTColor blackColor] colorWithAlphaComponent:0.0] atPosition:0.0];
overlayGradient = [overlayGradient addColorStop:[[CPTColor blackColor] colorWithAlphaComponent:0.3] atPosition:0.9];
overlayGradient = [overlayGradient addColorStop:[[CPTColor blackColor] colorWithAlphaComponent:0.7] atPosition:1.0];
// Add pie chart
piePlot = [[CPTPieChart alloc] init];
piePlot.dataSource = self;
piePlot.delegate = self;
piePlot.pieRadius = 80.0;
piePlot.identifier = #"Pie Chart 2";
piePlot.startAngle = M_PI_2;
piePlot.sliceDirection = CPTPieDirectionClockwise;
piePlot.borderLineStyle = [CPTLineStyle lineStyle];
//piePlot.sliceLabelOffset = 5.0;
piePlot.overlayFill = [CPTFill fillWithGradient:overlayGradient];
[pieGraph addPlot:piePlot];
pieGraph.title=#"GRAFICA SECTORES";
[piePlot release];
// Add some initial data
NSMutableArray *contentArray = [NSMutableArray arrayWithObjects:
[NSNumber numberWithDouble:20.0],
[NSNumber numberWithDouble:40.0],
[NSNumber numberWithDouble:30.0],
[NSNumber numberWithDouble:23],
[NSNumber numberWithDouble:60.0],
nil];
self.dataForChart = contentArray;
// Add legend
CPTLegend *theLegend = [CPTLegend legendWithGraph:pieGraph];
theLegend.numberOfColumns = 2;
theLegend.fill = [CPTFill fillWithColor:[CPTColor whiteColor]];
theLegend.borderLineStyle = [CPTLineStyle lineStyle];
theLegend.cornerRadius = 5.0;
pieGraph.legend = theLegend;
pieGraph.legendAnchor = CPTRectAnchorBottom;
pieGraph.legendDisplacement = CGPointMake(0.0, 30.0);
}
So in the legend I have always "Pie Chart 2".
PS: Sorry because of my poor english.
You need to add this method to your datasource:
-(NSString *)legendTitleForPieChart:(CPTPieChart *)pieChart
recordIndex:(NSUInteger)index;
It will be called for each index (corresponding to each pie slice). Simply return the correct title string for each one.

CorePlot inside detail view of Split View

I'm attempting to load a CPXYGraph into the detail view of a split view controller. I'm getting an EXC_BAD_ACCESS when it attempts to display the plot data.
I create a new project based on "Split View-based application". After adding the CorePlot framework I make the following modifications:
1- add a GraphController (.m, .h and .xib). The xib contains a UIView with a subordinate view of type CPLayerHostingView.
2- add the following line to the app delegate didFinishLaunchingWithOptions
[detailViewController performSelector:#selector(configureView) withObject:nil afterDelay:0];
3- add the following to DetailViewController configureView
CGRect graphFrame = CGRectMake(0, 43, 662, 450);
GraphController *graphController = [[[GraphController alloc]
initWithNibName:#"GraphController" bundle:nil] autorelease];
[graphController.view setFrame:graphFrame];
[self.view addSubview:graphController.view];
[graphController reloadData];
4- the reloadData method in GraphController is pretty much pasted from one of the CorePlot samples (DatePlot) and I will copy and paste (most of) it here-
-(void)reloadData
{
if (!graph)
{
[self parentViewController];
[self.view addSubview:layerHost];
// Create graph from theme
graph = [[CPXYGraph alloc] initWithFrame:CGRectZero];
CPTheme *theme = [CPTheme themeNamed:#"Dark Gradients"];
[graph applyTheme:theme];
....
[layerHost setHostedLayer: graph];
....
// Setup scatter plot space
CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
NSTimeInterval xLow = 0.0f;
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(xLow) length:CPDecimalFromFloat(oneDay*5.0f)];
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat(1.0) length:CPDecimalFromFloat(3.0)];
// Axes
CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet;
CPXYAxis *x = axisSet.xAxis;
x.majorIntervalLength = CPDecimalFromFloat(oneDay);
x.orthogonalCoordinateDecimal = CPDecimalFromString(#"2");
x.minorTicksPerInterval = 0;
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
dateFormatter.dateStyle = kCFDateFormatterShortStyle;
CPTimeFormatter *timeFormatter = [[[CPTimeFormatter alloc] initWithDateFormatter:dateFormatter] autorelease];
timeFormatter.referenceDate = refDate;
x.labelFormatter = timeFormatter;
CPXYAxis *y = axisSet.yAxis;
y.majorIntervalLength = CPDecimalFromString(#"0.5");
y.minorTicksPerInterval = 5;
y.orthogonalCoordinateDecimal = CPDecimalFromFloat(oneDay);
// Create a plot that uses the data source method
CPScatterPlot *dataSourceLinePlot = [[[CPScatterPlot alloc] init] autorelease];
dataSourceLinePlot.identifier = #"Date Plot";
dataSourceLinePlot.dataLineStyle.lineWidth = 3.f;
dataSourceLinePlot.dataLineStyle.lineColor = [CPColor greenColor];
dataSourceLinePlot.dataSource = self;
**[graph addPlot:dataSourceLinePlot];**
// Add some data
NSMutableArray *newData = [NSMutableArray array];
NSUInteger i;
for ( i = 0; i < 5; i++ ) {
NSTimeInterval x = oneDay*i;
id y = [NSDecimalNumber numberWithFloat:1.2*rand()/(float)RAND_MAX + 1.2];
[newData addObject:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSDecimalNumber numberWithFloat:x], [NSNumber numberWithInt:CPScatterPlotFieldX],
y, [NSNumber numberWithInt:CPScatterPlotFieldY],
nil]];
}
plotData = newData;
}
}
The offending line is [graph addPlot:dataSourceLinePlot]; If I comment this out the simulator comes up and displays the x and y axis of the graph and of course no data. Adding this line back causes the following SIGART-
2010-09-15 14:35:58.959 SplitViewWithCorePlot[17301:207] relabel <<CPScatterPlot: 0x4c458c0> bounds: {{0, 0}, {558, 386}}>
Program received signal: “EXC_BAD_ACCESS”.
Can anyone help?
It doesn't look like you're retaining the data array anywhere. Try changing the last statement to
plotData = [newData retain];
or, if you have a property defined for it,
self.plotData = newData;
Eric

build and analyze not working in my project

In my iPhone Project when i select build and analyze (shift + mac + A ) it will give me all potential memory leak in my project... but in my current project it is not working... when i intentionally put a memory leak and select build and analyze... it doesn't give me any potential memory leak as analyzer result
if i write
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:6];
NSMutableArray *tempArrayfinal = [[NSMutableArray alloc] initWithCapacity:12];
and doesn't release it... it is not giving me any potential leak but if i write
NSString *leakyString = [[NSString alloc] initWithString:#"Leaky String "];
NSLog(#"%#",leakyString);
here it gives me potential leak as analyzer result...why it is not giving potential leak in NSMutableArray and why it gives potential leak in NSString ?... how can i rely on Build and analyze for memory leak...
I've run the app with Leak tool and it is showing me leak in tempArray and tempArrayfinal
Here is my function
- (void)viewDidLoad
{
[super viewDidLoad];
maxOnSnaxAppDelegate *delegate = (maxOnSnaxAppDelegate *)[[UIApplication sharedApplication] delegate];
lblMessage.tag = MESSAGE_LABEL;
lblGuess.tag = GUESS_LABEL;
lblScore.tag = SCORE_LABEL;
self.gameCompleteView.tag = FINAL_SCORE_VIEW;
lblFinalScore.tag = FINAL_SCORE_LABEL;
lblGuess.text = #"";
lblMessage.text = #"";
lblScore.text = #"";
int row = 0;
int column = 0;
maxImagrArray = [[NSMutableArray alloc] init];
for(UIView *subview in [self.view subviews]) {
if([subview isKindOfClass:[CustomImageView class]])
{
[subview removeFromSuperview];
}
}
for(int i = 0 ; i < 12 ; i++)
{
if(i%3 == 0 && i != 0)
{
row++;
column = -1;
}
if(i != 0 )
{
column++;
//row = 0;
}
CustomImageView *tempImageView = [[CustomImageView alloc] initWithImage:[UIImage imageNamed:#"max-img.png"]];
tempImageView.frame = CGRectMake((column*tempImageView.frame.size.width) + 45, (row*tempImageView.frame.size.height)+ 60, tempImageView.frame.size.width, tempImageView.frame.size.height);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, tempImageView.bounds);
[self.view addSubview:tempImageView];
tempImageView.tag = i+1;
tempImageView.userInteractionEnabled = YES;
[maxImagrArray addObject:tempImageView];
[tempImageView setIndex:i];
[tempImageView release];
}
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithCapacity:6];
NSMutableArray *tempArrayfinal = [[NSMutableArray alloc] initWithCapacity:12];
for(int i = 0 ; i < 12 ; i++)
{
if(i < 6)
{
int temp = (arc4random() % 10) + 1;
NSString *tempStr = [[NSString alloc] initWithFormat:#"%d",temp];
[tempArray insertObject:tempStr atIndex:i];
[tempArrayfinal insertObject:tempStr atIndex:i];
[tempStr release];
}
else
{
int temp = (arc4random() % [tempArray count]);
[tempArrayfinal insertObject: (NSString *)[tempArray objectAtIndex:temp] atIndex:i];
//int index = [(NSString *)[tempArray objectAtIndex:temp] intValue];
[tempArray removeObjectAtIndex:temp];
}
CustomImageView *tmpCustom = [maxImagrArray objectAtIndex:i];
tmpCustom.frontImageIndex = [(NSString *)[tempArrayfinal objectAtIndex:i] intValue];
NSLog(#"%d",tmpCustom.frontImageIndex);
}
[maxImagrArray release];
delegate.time = 60.0;
timer = nil;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(countDown) userInfo:nil repeats:YES];
delegate.view = self.view;
//[tempArray release];
//[tempArrayfinal release];//these 2 lines are deliberately commented to see
//...it is not showing any potential memory leak though....
delegate.viewController = self;
}
please help...
[tempArray insertObject:tempStr atIndex:i];
[tempArrayfinal insertObject:tempStr atIndex:i];
are the culprits... when i uncomment these 2 lines.. it stops giving me the warning... i don't know why...
You shouldn't really rely on the Build and Analyze tool. It does not always catch all leaks. Threre is no substitute for following the memory management rules from apple (apart from garbage collection on OS X). However, I'm not sure why it isn't catching such a simple leak. I tried at line in a method and it did give me a result. Are you sure its not in an if statement, because I've found that sometimes in an if statement it won't correct you.

Detect same images name {iPhone SDK}

i want create image animation , i have 50 images with png format now i want set images name ... something like this but doesnt work !
my images name are : iamge_0000 to image_0050
pasheAnimation.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"pashe_0000.png"],nil];
[pasheAnimation setAnimationRepeatCount:5];
pasheAnimation.animationDuration = 4;
[pasheAnimation startAnimating];
??!?!?!?
jason Code [EDITED] :
NSMutableArray* myImages = [[[NSMutableArray alloc] initWithCapacity:607] autorelease];
for( int i = 1; i <= 607; i++ ) {
[myImages addObject:[UIImage imageNamed:[NSString stringWithFormat:#"p%d.png",i]]];
}
butterflyView.animationImages = myImages;
[butterflyView setAnimationRepeatCount:100];
butterflyView.animationDuration = 0;
[butterflyView startAnimating];
// There are actually 51 images in this series (0000-0050)
NSMutableArray* myImages = [[[NSMutableArray alloc] initWithCapacity:51] autorelease];
for( int i = 0; i <= 50; i++ ) {
[myImages addObject:[UIImage imageNamed:[NSString stringWithFormat:#"image_%04d.png", i]]?:[NSNull null]];
}
You actually have 51 images, from zero to fifty.
NSMutableArray *myImages = [NSMutableArray arrayWithCapacity:51];
for (NSUInteger idx = 0; idx <= 50; idx++) {
NSString *filename = [NSString stringWithFormat:"image_%04d.png", idx];
UIImage *image = [UIImage imageNamed:filename];
if (image) {
[myImages addObject:image];
}
else {
NSLog(#"Could not add %#", filename); // could also throw exception, if you want
}
}