Add UIView in UIScrollView - ios

I am using ScrollView instead of UICollectionView for showing image. After three images the fourth image will be placed in below the first Like
1 2 3
4 5 6
7 8 9
Please any one share the logic of this.
self.dataArr = [#[#"1", #"1", #"1", #"2", #"2", #"1", #"2", #"3", #"1", #"2", #"4", #"5", #"3", #"4", #"5", #"1", #"6", #"7"]mutableCopy];
int x = 5; int y = 5;
for (int i = 0; i< self.dataArr.count; i++) {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(x, y, 100, 100)];
view.backgroundColor = [UIColor greenColor];
[contentSv addSubview:view];
x += 105;
y = ? contentSv.contentSize = CGSizeMake(320, y);
}

self.dataArr = [#[#"1", #"1", #"1", #"2", #"2", #"1", #"2", #"3", #"1", #"2", #"4", #"5", #"3", #"4", #"5", #"1", #"6", #"7"]mutableCopy];
int x = 5; int y = 5; int count = 0;
for (int i = 0; i< self.dataArr.count; i++) {
count++;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(x, y, 100, 100)];
view.backgroundColor = [UIColor greenColor];
[contentSv addSubview:view];
x += 105;
if (count == 4){
count = 0;
y+= 105; //set your appropriate height here.
x = 5;
}
//y = ? contentSv.contentSize = CGSizeMake(320, y);
}
Hope this helps.

Related

How to display string value on xAxis label in line chart(MP chart 3.0)

In my objective c project I need to Migrating MPChart from 2.2 to 3.0 for supporting my project in Xcode 9.2. but sum code is changed now.
view DidLoad
xAxis.valueFormatter = self;
chart update function
- (void)setDataCount:(int)count range:(double)range
{
xVals = [[NSMutableArray alloc] init];
for (int i = 0; i < dateAll.count; i++)
{
[xVals addObject:[dateAll objectAtIndex:i]];
}
NSLog(#"xVals %#",xVals);
NSMutableArray *yVals = [[NSMutableArray alloc] init];
for (int i = 0; i < arrtymHr.count; i++)
{
double vals = [[NSString stringWithFormat:#"%#.%#",[arrtymHr objectAtIndex:i],[arrtymMnt objectAtIndex:i]] doubleValue];
[yVals addObject:[[ChartDataEntry alloc] initWithX:i y:vals]];
}
NSLog(#"yVals %#",yVals);
LineChartDataSet *set1 = [[LineChartDataSet alloc] initWithValues:yVals label:#"DataSet 1"];
set1.axisDependency = AxisDependencyRight;
[set1 setColor:[UIColor colorWithRed:51/255.f green:181/255.f blue:229/255.f alpha:1.f]];
[set1 setCircleColor:[UIColor clearColor]];
set1.lineWidth = 2.0;
set1.circleRadius = 3.0;
set1.fillAlpha = 0.70;
set1.fillColor = [UIColor colorWithRed:51/255.f green:181/255.f blue:229/255.f alpha:1.f];
set1.highlightColor = [UIColor colorWithRed:244/255.f green:117/255.f blue:117/255.f alpha:1.f];
set1.drawCircleHoleEnabled = YES;
set1.drawFilledEnabled = !set1.isDrawFilledEnabled;
NSMutableArray *yVals2 = [[NSMutableArray alloc] init];
for (int i = 0; i < Allpost.count; i++)
{
double vals = [[Allpost objectAtIndex:i]doubleValue];
[yVals2 addObject:[[ChartDataEntry alloc] initWithX:i y:vals]];
}
NSLog(#"yVals 2 %#",yVals2);
LineChartDataSet *set2 = [[LineChartDataSet alloc] initWithValues:yVals2 label:#"DataSet 2"];
set2.axisDependency = AxisDependencyLeft;
[set2 setColor:[UIColor colorWithRed:245/255.f green:130/255.f blue:32/255.f alpha:1.f]];
[set2 setCircleColor:[UIColor clearColor]];
set2.lineWidth = 3.0;
set2.circleRadius = 3.0;
set2.fillAlpha = 1.0;
set2.fillColor = UIColor.redColor;
set2.highlightColor = [UIColor colorWithRed:244/255.f green:117/255.f blue:117/255.f alpha:1.f];
set2.drawCircleHoleEnabled = YES;
NSMutableArray *dataSets = [[NSMutableArray alloc] init];
[dataSets addObject:set1];
[dataSets addObject:set2];
LineChartData *data = [[LineChartData alloc] initWithDataSets:dataSets];
[data setValueTextColor:[UIColor clearColor]];
[data setValueFont:[UIFont systemFontOfSize:9.f]];
_chartView.data = data;
}
formatter function
- (NSString *)stringForValue:(double)value
axis:(ChartAxisBase *)axis
{
return [xVals objectAtIndex:value];
}
but the problem is the array only have one value but it displays more than one.
Printed Array
xVals (
"03/08",
"03/16",
"03/16",
"03/16"
)
yVals (
"ChartDataEntry, x: 0.0, y 0.0",
"ChartDataEntry, x: 1.0, y 0.0",
"ChartDataEntry, x: 2.0, y 0.0",
"ChartDataEntry, x: 3.0, y 0.0"
)
yVals 2 (
"ChartDataEntry, x: 0.0, y 5.5",
"ChartDataEntry, x: 1.0, y 7.0",
"ChartDataEntry, x: 2.0, y 7.0",
"ChartDataEntry, x: 3.0, y 3.0"
)
As per new Charts update you need to create ChartDataEntry in which you can add both X & Y value and than add it into LineChartDataSet
Please check below code :
//Create values array
NSMutableArray *values = [[NSMutableArray alloc] init];
//Create
[yValArray enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL * _Nonnull stop) {
[values addObject:[[ChartDataEntry alloc] initWithX:idx y:obj];
}];
In above code we are adding index in DataEntry form 0 .... N.
//Add dataEntry Object into values array
[values addObject:dataEntry];
//Create DataSet with values array
LineChartDataSet *set1 = [[LineChartDataSet alloc] initWithValues:values label:#"your_label_for_data_set"];
//Add Line Chart Data inro Chart.
LineChartData *data = [[LineChartData alloc] initWithDataSet:set1];
//Set Data to Line Chart
_lineChartTrend.data = data;
Now use your Formatter and return value based on index like below
- (NSString *)stringForValue:(double)value
axis:(ChartAxisBase *)axis
{
if (yourLineChart.xAxis == axis) {
return [xValArray objectAtIndex:value];
}
}
Where value is your index which we have added in DataEntry.
By Doing this you will get your X & Y value on your line Chart.
Edit:
Based on your comment and Question updation you need to add one more property for your XAxis so that it will not repeat XAxis value and will remain same as per your array, set below code and you will get expected output on your chart.
ChartXAxis *xAxis = self.lineChart.xAxis;
xAxis.granularity = 1.0;
Try this and let me know is it working or not.
Try This
#interface ViewController ()<IChartAxisValueFormatter>
viewDidLoad
xAxis.axisRange = 1;
xAxis.granularity = 1;
xAxis.valueFormatter =self;
#pragma mark - IAxisValueFormatter
- (NSString * _Nonnull)stringForValue:(double)value axis:(ChartAxisBase * _Nullable)axis
{
NSString *xAxisStringValue = #"";
int myInt = (int)value;
if(xVals.count > myInt)
{
xAxisStringValue = [xVals objectAtIndex:myInt];
return xAxisStringValue;
}
else
{
return 0;
}
}

create JSON from 2 arrays in IOS

I'm trying to create dictionary to POST JSON data to server:
NSArray *keys = [NSArray arrayWithObjects:#"lat", #"lon", nil];
NSArray *values = [NSArray arrayWithObjects: orderClass.extraLat, orderClass.extraLon, nil];
NSDictionary *postDict = [NSDictionary dictionaryWithObjects:values forKeys:keys];
this gives me:
{
lat = (
"54.720746",
"54.719206",
"54.717466"
);
lon = (
"56.011108",
"56.008510",
"56.007031"
);
}
But the aim is to POST data from arrays in format:
[{"lat":"54.720746", "lon":"56.011108" },
{ "lat":"54.719206", "lon":"56.008510"},
{ "lat":"54.717466", "lon":"56.007031"}]
Need your help.
Thanks for paying attention!
As I said in the comment - you need to reverse the steps towards your goal. First dictionaries, then array. And you'll get what you want.
NSArray *keys = [NSArray arrayWithObjects:#"lat", #"lon", nil];
NSArray *lats = [NSArray arrayWithObjects:#"1", #"2", #"3", nil];
NSArray *lons = [NSArray arrayWithObjects:#"4", #"5", #"6", nil];
// your way (not what you want)
NSArray *values = [NSArray arrayWithObjects: lats, lons, nil];
NSDictionary *postDict = [NSDictionary dictionaryWithObjects:values forKeys:keys];
// my recommendation based on what you want
NSMutableArray *postData = [[NSMutableArray alloc] init];
for (int i = 0; i < lats.count; i++) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:[lats objectAtIndex:i] forKey:#"lat"];
[dict setObject:[lons objectAtIndex:i] forKey:#"lon"];
[postData addObject:dict];
}
This will get you these results:
(lldb) po postDict
{
lat = (
1,
2,
3
);
lon = (
4,
5,
6
);
}
And
(lldb) po postData
<__NSArrayM 0x7ffb5be4d950>(
{
lat = 1;
lon = 4;
},
{
lat = 2;
lon = 5;
},
{
lat = 3;
lon = 6;
}
)

How to replace array values to same+10 [duplicate]

This question already has an answer here:
Fill NSMutableArray in a for loop [duplicate]
(1 answer)
Closed 8 years ago.
How I can replace elements?
I try like this, but it does not work
NSMutableArray* marray = [[NSMutableArray alloc] initWithObjects:#"1", #"2", #"3", nil];
for (int i = 0; [marray count]; i++) {
NSInteger curentVal = [[marray objectAtIndex:i] intValue];
curentVal += 5;
[marray replaceObjectAtIndex:i withObject:curentVal];
}
You need to convert curentVal back to an object, in this case a NSString.
There is also a typeo in the for statement.
NSMutableArray* marray = [[NSMutableArray alloc] initWithObjects:#"1", #"2", #"3", nil];
NSLog(#"marray: %#", marray);
for (NSInteger i = 0; i<[marray count]; i++) {
NSInteger curentVal = [[marray objectAtIndex:i] intValue];
curentVal += 5;
NSString *curentValString = [NSString stringWithFormat:#"%ld", (long)curentVal];
[marray replaceObjectAtIndex:i withObject: curentValString];
}
NSLog(#"marray: %#", marray);
Output:
marray: (
1,
2,
3
)
marray: (
6,
7,
8
)
Here is the same approach with NSNumbers:
NSMutableArray* marray = [[NSMutableArray alloc] initWithObjects:#1, #2, #3, nil];
for (NSInteger i = 0; i<[marray count]; i++) {
NSInteger curentVal = [[marray objectAtIndex:i] intValue];
curentVal += 5;
[marray replaceObjectAtIndex:i withObject:#(curentVal)];
}
curentVal is not an object. You should put:
[marray replaceObjectAtIndex:i withObject:#(curentVal)];
so curentVal is converted to an NSNumber
Also you probably want to deal with numbers, so put:
NSMutableArray* marray = [[NSMutableArray alloc] initWithObjects:#1, #2, #3, nil];

UISegmentedControl index

I am trying to list out the selected index of many UISegmentControls. I set 5 of them on 1, 2, 3, 4, 5 respectively, and the result after using this code (in the array) is: 2, 2, 0, 0, 0...
for (UISegmentedControl *seg in segmentArray)
{
NSString* xWrapped = [NSString stringWithFormat:#"%d", seg.selectedSegmentIndex+1];
[difficultyH addObject: xWrapped];
}
Why??
EDIT:
This is how the segments are created:
//segment controll
NSArray *itemArray2 = [NSArray arrayWithObjects: #"very easy", #"easy", #"ok", #"hard", #"challenging", nil];
UISegmentedControl *segmentedControl2 = [[UISegmentedControl alloc] initWithItems:itemArray2];
segmentedControl2.frame = CGRectMake(480, -60, 130, 350);
segmentedControl2.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl2.selectedSegmentIndex = val - 1;
[segmentedControl2 addTarget:self action:#selector(segmentedControlHomework:) forControlEvents:UIControlEventValueChanged];
segmentedControl2.transform =
CGAffineTransformRotate(segmentedControl2.transform, degreesToRadians(90));
NSArray *arr = [segmentedControl2 subviews];
for (int i = 0; i < [arr count]; i++) {
UIView *v = (UIView*) [arr objectAtIndex:i];
NSArray *subarr = [v subviews];
for (int j = 0; j < [subarr count]; j++) {
if ([[subarr objectAtIndex:j] isKindOfClass:[UILabel class]]) {
UILabel *l = (UILabel*) [subarr objectAtIndex:j];
l.transform = CGAffineTransformMakeRotation(- M_PI / 2.0); //do the reverse of what Ben did
}
}
}
[image1 addSubview:segmentedControl2];
segmentedControl2.tag = i;
[segmentArray addObject: segmentedControl2];
//segment controll

How to plot a graph real time using coreplot?

I'm trying to plot the decibel values of sound on a graph(CPScatterPlot) using coreplot. But the problem is I'm getting the graph with a line that is perpendicular for Y axis, and it's moving up and down on the Y axis with respect to the changes in the decibel values. I need to plot a graph like this.
here is my code:
`
-(void) generateDataSamples
{
samples = [[NSMutableArray alloc]initWithCapacity:NUM_SAMPLES];
for (int i=0; i < NUM_SAMPLES; i++)
{
// peakVal is a variable that holds the decibel value
NSDictionary *sample = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:peakVal],Y_VAL,nil];
[samples addObject:sample];
}
}
-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot;
{
return [samples count];
}
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index{
NSDictionary *sample = [samples objectAtIndex:index];
NSDecimalNumber *num = [NSDecimalNumber zero];
if (fieldEnum == CPScatterPlotFieldX)
{
num = (NSDecimalNumber *) [NSDecimalNumber numberWithInt:index + 1];
}
else if (fieldEnum == CPScatterPlotFieldY)
{
return [sample valueForKey:Y_VAL];
}
return num;
}
So, what should I do to get a graph as in the figure above? Please help me, I'm new on here.
And one more, as you can in the above picture, the Y axis labels are placed inside the plot area, how it can be done?
Here is my entire code, please suggest the modifications:
#import "MicBlowViewController.h"
#import "SecondVC.h"
#define DBOFFSET -74.0
#define START_POINT 0.0
#define END_POINT 100.0
#define NUM_SAMPLES 200.0
#define MAX_PEAK 100.0
#define X_VAL #"X_VAL"
#define Y_VAL #"Y_VAL"
#define S_VAL #"S_VAL"
#implementation MicBlowViewController
#synthesize avgLabel, peakLabel,absValue,pageControl;
-(void)reloadData
{
if(!graph)
{
//setting graph
double xAxisStart = START_POINT;
double xAxisLength = END_POINT - START_POINT;
double maxY = 100;//[[samples valueForKeyPath:#"#max.Y_VAL"] doubleValue];
double yAxisStart = START_POINT;
double yAxisLength = maxY+3;
xVal=START_POINT+0.1;
hostingView = [[CPGraphHostingView alloc] initWithFrame:CGRectMake(0, 79, 320, 361)];
[self.view addSubview:hostingView];
graph = [[CPXYGraph alloc] initWithFrame:CGRectMake(0, 79, 320, 361)];
hostingView.hostedGraph = graph;
CPTheme *theme = [CPTheme themeNamed:kCPDarkGradientTheme];
[graph applyTheme:theme];
graph.paddingTop = 0.0;
graph.paddingBottom = 0.0;
graph.paddingLeft = 0.0;
graph.paddingRight = 0.0;
[[graph defaultPlotSpace] setAllowsUserInteraction:TRUE];
CPXYAxisSet *axisSet = (CPXYAxisSet *)graph.axisSet;
axisSet.yAxis.labelOffset=0.1;
CPXYAxis *x = axisSet.xAxis;
x.majorIntervalLength = CPDecimalFromDouble(10.0);
x.orthogonalCoordinateDecimal = CPDecimalFromInteger(0);
x.minorTicksPerInterval = 1;
CPXYAxis *y = axisSet.yAxis;
y.majorIntervalLength=CPDecimalFromDouble(10.0);
y.orthogonalCoordinateDecimal = CPDecimalFromInteger(0);
y.minorTicksPerInterval = 1;
y.tickDirection = CPSignPositive;
y.labelAlignment = CPAlignmentLeft;
y.alternatingBandFills = [NSArray arrayWithObjects:[[CPColor whiteColor] colorWithAlphaComponent:0.1], [NSNull null], nil];
CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromDouble(xAxisStart)
length:CPDecimalFromDouble(xAxisLength)];
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromDouble(yAxisStart)
length:CPDecimalFromDouble(yAxisLength)];
CPScatterPlot *dataSourceLinePlot = [[CPScatterPlot alloc] init];
dataSourceLinePlot.dataSource = self;
//[dataSourceLinePlot insertDataAtIndex:[samplesY count]-1 numberOfRecords:1];
CPMutableLineStyle *lineStyle = [[dataSourceLinePlot.dataLineStyle mutableCopy] autorelease];
lineStyle.lineWidth = 2.f;
lineStyle.lineColor = [CPColor cyanColor];
dataSourceLinePlot.dataLineStyle = lineStyle;
[graph addPlot:dataSourceLinePlot];
[dataSourceLinePlot release];
[graph release];
[hostingView release];
}
}
- (void)generateData
{
// if (plotData == nil) {
NSMutableArray *contentArray = [NSMutableArray array];
for (NSUInteger i = 0; i < 200; i++) {
//double test = (double)[peakLabel.text doubleValue];
absValue.text =[NSString stringWithFormat:#"%.2f",peakVal];
id x = [NSDecimalNumber numberWithDouble:1.0 + i ];
id y = [NSDecimalNumber numberWithDouble:peakVal * rand()/(double)RAND_MAX + 0.05];
[contentArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, #"x", y, #"y", nil]];
}
plotData = [contentArray retain];
//}
}
-(NSUInteger)numberOfRecordsForPlot:(CPPlot *)plot ;
{
return [plotData count];
}
-(NSNumber *)numberForPlot:(CPPlot *)plot field:(NSUInteger)fieldEnum
recordIndex:(NSUInteger)index;
{
NSNumber *num = [[plotData objectAtIndex:index] valueForKey:(fieldEnum == CPScatterPlotFieldX ? #"x" : #"y")];
if (fieldEnum == CPScatterPlotFieldY) {
num = [NSNumber numberWithDouble:[num doubleValue]];
}
return num;
}
- (void)viewDidLoad {
[super viewDidLoad];
pageControl = [[UIPageControl alloc]init];
[pageControl addTarget:self action:#selector(changePage) forControlEvents:UIControlEventValueChanged];
samplesY = [[NSMutableArray alloc]init];
//checking for sound
NSURL *url = [NSURL fileURLWithPath:#"/dev/null"];
NSDictionary *settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
[NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
[NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
[NSNumber numberWithInt: AVAudioQualityMax], AVEncoderAudioQualityKey,
nil];
NSError *error;
recorder = [[AVAudioRecorder alloc] initWithURL:url settings:settings error:&error];
if (recorder) {
[recorder prepareToRecord];
recorder.meteringEnabled = YES;
[recorder record];
levelTimer = [NSTimer scheduledTimerWithTimeInterval: 0.03 target: self selector: #selector(levelTimerCallback:) userInfo: nil repeats: YES];
}// else
//NSLog([error description]);
}
- (void)levelTimerCallback:(NSTimer *)timer {
// getting decibel values....
[recorder updateMeters];
const double ALPHA = 0.05;
double peakPowerForChannel = pow(10, (0.05 * [recorder peakPowerForChannel:0]));
lowPassResults = ALPHA * peakPowerForChannel + (1.0 - ALPHA) * lowPassResults;
NSLog(#"Average input: %f Peak input: %f Low pass results: %f",
[recorder averagePowerForChannel:0], [recorder peakPowerForChannel:0], lowPassResults);
peakval=fabs([recorder peakPowerForChannel:0]);
double avgval=fabs([recorder averagePowerForChannel:0]);
peakVal=MAX_PEAK - peakval;
avgVal=MAX_PEAK - avgval;
NSLog(#"First: %.2f",peakVal);
avgLabel.text=[NSString stringWithFormat:#"%.2f",avgVal];
peakLabel.text=[NSString stringWithFormat:#"%.2f",peakVal];
if (lowPassResults < 0.95)
NSLog(#"Mic blow detected: %d",lowPassResults);
[self generateData];
[self reloadData];
}
- (IBAction) changePage:(id)sender{
SecondVC *vc = [[SecondVC alloc]init];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:vc animated:YES];
[vc release];
}
- (void)dealloc {
[peakLabel.text release];
[avgLabel.text release];
[samples release];
[levelTimer release];
[recorder release];
[super dealloc];
}
#end
It looks like you're using the same peakVal for every data point. Check the -generateDataSamples method and make sure you're storing the correct values in the samples array. If you already have the data in an array, you can skip that method completely and just do the lookup by index in -numberForPlot:field:recordIndex:.
Also, check the xRange and yRange on the plot space to make sure they fit your data. Remember that plot ranges are like NSRange—they are created using a starting location and length, not start and end values.
To move the labels to the right side of the y-axis, use yAxis.tickDirection = CPTSignPositive;.
Edit in response to the comments
Don't call -generateDataSamples every time you get new data. Instead, add the new value to the samples array. Don't forget to initialize the array before using it for the first time.
NSDictionary *sample = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithDouble:peakVal],Y_VAL,nil];
[samples addObject:sample];
Once the data is in the array, tell Core Plot to load only the new point. This will be faster than reloading all of the data every time you update.
[myScatterPlot insertDataAtIndex:(samples.count - 1)
numberOfRecords:1];
You can use the CPTPlot method -deleteDataInIndexRange: to remove old data points if you don't need to keep all of the history in the graph. Don't forget to remove the corresponding point from the samples array also.

Resources