How to create area graph with ios charts? - swift

I am trying to create an area graph with the min and max value for each points.But did not found anywhere .I guess setting the background color in the area between two line graph should solve this.
Tried setting fillColor for two data sets as.
.fillColor = UIColor.lightGrayColor()
.drawFilledEnabled = true
I have seen from demo project.It can be done as
set1 = [[LineChartDataSet alloc] initWithValues:yVals1 label:#"DataSet 1"];
set1.axisDependency = AxisDependencyLeft;
[set1 setColor:[UIColor colorWithRed:255/255.0 green:241/255.0 blue:46/255.0 alpha:1.0]];
set1.drawCirclesEnabled = NO;
set1.lineWidth = 2.0;
set1.circleRadius = 3.0;
set1.fillAlpha = 1.0;
set1.drawFilledEnabled = YES;
set1.fillColor = UIColor.whiteColor;
set1.highlightColor = [UIColor colorWithRed:244/255.0 green:117/255.0 blue:117/255.0 alpha:1.0];
set1.drawCircleHoleEnabled = NO;
set1.fillFormatter = [ChartDefaultFillFormatter withBlock:^CGFloat(id<ILineChartDataSet> _Nonnull dataSet, id<LineChartDataProvider> _Nonnull dataProvider) {
return _chartView.leftAxis.axisMinimum;
}];
set2 = [[LineChartDataSet alloc] initWithValues:yVals2 label:#"DataSet 2"];
set2.axisDependency = AxisDependencyLeft;
[set2 setColor:[UIColor colorWithRed:255/255.0 green:241/255.0 blue:46/255.0 alpha:1.0]];
set2.drawCirclesEnabled = NO;
set2.lineWidth = 2.0;
set2.circleRadius = 3.0;
set2.fillAlpha = 1.0;
set2.drawFilledEnabled = YES;
set2.fillColor = UIColor.whiteColor;
set2.highlightColor = [UIColor colorWithRed:244/255.0 green:117/255.0 blue:117/255.0 alpha:1.0];
set2.drawCircleHoleEnabled = NO;
set2.fillFormatter = [ChartDefaultFillFormatter withBlock:^CGFloat(id<ILineChartDataSet> _Nonnull dataSet, id<LineChartDataProvider> _Nonnull dataProvider) {
return _chartView.leftAxis.axisMaximum;
}];
But i cannot convert the syntax in swift.
set2.fillFormatter = [ChartDefaultFillFormatter withBlock:^CGFloat(id<ILineChartDataSet> _Nonnull dataSet, id<LineChartDataProvider> _Nonnull dataProvider) {
return _chartView.leftAxis.axisMaximum;
}];

You don't have to set the fillFormatter, unless you need to adjust the fill-behaviour. As far as I am concerned the static withBlock: does not exist in the Swift interface. Instead you have to create you own ChartFillFormatter implementation and implement the public func getFillLinePosition(dataSet dataSet: ILineChartDataSet, dataProvider: LineChartDataProvider) -> CGFloat function.
You should not have to do anything else than setting the drawFilledEnabled and fillColor on the LineChartDataSet and then of course use the LineChartView.
So if you really need the fill formatter you will have to do something like this:
public class MyFillFormatter: NSObject, ChartFillFormatter
{
private let _chartView: LineChartView
public override init(chartView: LineChartView)
{
super.init()
_chartView = chartView
}
public func getFillLinePosition(dataSet dataSet: ILineChartDataSet, dataProvider: LineChartDataProvider) -> CGFloat
{
return _chartView.leftAxis.axisMaximum
}
}
And then set it as:
set1.fillFormatter = MyFillFormatter(chartView: lineChartView)

There is now swift example for what you asked:
https://github.com/danielgindi/Charts/blob/master/ChartsDemo-iOS/Swift/Demos/LineChartFilledViewController.swift
Looks like this in the demo app:

Related

How To Change a Variable Name Depending on Another Variable?

I have a UIImageView called platform1, platform2, platform3, etc. I have an int called platformNumber coming from one method (method1) into another method (method2).
Method2 (contents not useful to my question):
CGPoint origin = platform1.center;
CGPoint target = CGPointMake(platform1.center.x, platform1.center.y+10);
CABasicAnimation *bounce = [CABasicAnimation animationWithKeyPath:#"position.y"];
bounce.duration = 0.1;
bounce.fromValue = [NSNumber numberWithInt:origin.y];
bounce.toValue = [NSNumber numberWithInt:target.y];
bounce.repeatCount = 1;
bounce.autoreverses = YES;
[platform1.layer addAnimation:bounce forKey:#"position"];
How do I change it so whereever platform1.center.x appears, it changes to platform[platformNumber] depending in the platformNumber value passed through?
Thanks, any help would be much appreciated!
The answers proposing KVC are not scalable at all; please don't do that. You can't declare a variable at runtime, so would will be stuck with however many image views you could attach a property too.
You need to build an array of your image views and iterate them. I repeat, KVC is not intended for this.
NSMutableArray *imageviews = [[NSMutableArray alloc] init];
//...
[imageViews addObject:platform1];
[imageViews addObject:platform2];
[imageViews addObject:platform3];
//...
Then iterate the array:
foreach (UIImageView *imgView in _imageViews) {
CGPoint origin = imgView.center;
CGPoint target = CGPointMake(imgView.center.x, imgView.center.y+10);
CABasicAnimation *bounce = [CABasicAnimation animationWithKeyPath:#"position.y"];
bounce.duration = 0.1;
bounce.fromValue = [NSNumber numberWithInt:origin.y];
bounce.toValue = [NSNumber numberWithInt:target.y];
bounce.repeatCount = 1;
bounce.autoreverses = YES;
[imgView.layer addAnimation:bounce forKey:#"position"];
}
int index = 3;
_imageViews[index]
returns you platform2 in your example (array start at 0, so subtract one)
Alternatively you can also create a function
-(UIImageView*)getPlatformForNumber:(int)number {
switch(number)
{
case 1:
return platform1;
case 2:
return platform2;
...
}
// should not come here
return nil;
}
and call that function where necessary. Sometimes that solution comes in handy - but the array proposed in davbryn's solution is of course more scalable.

If/Then statements using UISwitch in xcode

I am trying to get my app to run one mathematical formula when UISwitch is set to "On" position, and another when it's set to "off" position.
I'm trying to lay it out like this:
if switch = on, then [first formula]
if switch = off, then [second formula]
how would I code this?
=============
EDIT:
This is how I am currently trying to code it.
-(IBAction)switchValueChanged:(UISwitch *)sender
{
if(sender.on)
{
-(float)conver2inches: (NSString *)mmeters {
return [mmeters floatValue]/25.4f;
}
-(IBAction)calculate:(id)sender{
float answer = [self conver2inches:entry.text];
output.text=[NSString stringWithFormat:#"%f",answer];}}
else{
-(float)conver2mmeters:(NSString *)inches {
return [inches floatValue]*25.4f;
}
-(IBAction)calculate:(id)sender{
float answer = [self conver2mmeters:entry.text];
output.text=[NSString stringWithFormat:#"%f",answer];
}}
}
Given:
#property (nonatomic) IBOutlet UISwitch *switch;
Then:
self.switch.on ? [self formula1] : [self formula2];
You need to hook up a function like this to uiswitch's value changed uievent.
-(IBAction) switchValueChanged:(UISwitch *) sender
{
if(sender.on)
{
...
}
else
{
...
}
}
Here is a example of using uiswich on or off in a statement:
-(IBAction)onOffSwitch:(id)sender{
if(onOffSwitch.on) {
// lights on
[onOffLabel setText:#"Lights Currently On"];
onOffLabel.textColor = [UIColor blackColor];
self.view.backgroundColor = [UIColor colorWithRed:255.0/255.0 green:219.0/255.0 blue:52.0/255.0 alpha:1.0];
}
else {
// lights off
self.view.backgroundColor = [UIColor blackColor];
[onOffLabel setText:#"Lights Currently Off"];
onOffLabel.textColor = [UIColor whiteColor];
}
}
UISwitch has a property named on which you can use to detect if the switch is on or off. Or are you asking how to write code that acts when the switch is actually flipped?

GPUImage overlay live video with corner detection

Trying to get a basic filter working with GPUImage, but not sure how to properly set it up to display the crosshairs over the live video feed, when detecting corners. I tried adding the crosshairs to the blend filter, along with the video, then add that to the gpuimageview, but all I get is a white screen. Any ideas?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack];
videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
GPUImageView *filteredVideoView = (GPUImageView *)self.view;
GPUImageCrosshairGenerator *crosshairGenerator = [[GPUImageCrosshairGenerator alloc] init];
crosshairGenerator.crosshairWidth = 15.0;
[crosshairGenerator forceProcessingAtSize:CGSizeMake(480.0, 640.0)];
customFilter = [[GPUImageHarrisCornerDetectionFilter alloc] init];
[customFilter setCornersDetectedBlock:^(GLfloat* cornerArray, NSUInteger cornersDetected, CMTime frameTime){
[crosshairGenerator renderCrosshairsFromArray:cornerArray count:cornersDetected frameTime:frameTime];
NSLog(#"corners: %u", cornersDetected);
}];
GPUImageAlphaBlendFilter *blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
[blendFilter forceProcessingAtSize:CGSizeMake(480.0, 640.0)];
[videoCamera addTarget:blendFilter];
[crosshairGenerator addTarget:blendFilter];
[blendFilter addTarget:filteredVideoView];
[videoCamera startCameraCapture];
}
This is how ur code should be in Swift 2.0
var liveCam:GPUImageVideoCamera!
var edgesDetector:GPUImageHarrisCornerDetectionFilter!
var crosshairGenerator:GPUImageCrosshairGenerator!
#IBOutlet weak var camView: GPUImageView!
override func viewDidLoad() {
super.viewDidLoad()
liveCam = GPUImageVideoCamera(sessionPreset: AVCaptureSessionPreset640x480, cameraPosition: .Back)
liveCam.outputImageOrientation = .Portrait
crosshairGenerator = GPUImageCrosshairGenerator()
crosshairGenerator.crosshairWidth = 15
crosshairGenerator.forceProcessingAtSize(CGSize(width: 480, height: 640))
edgesDetector = GPUImageHarrisCornerDetectionFilter()
edgesDetector.blurRadiusInPixels = 2 //Default value
edgesDetector.threshold = 0.2 //Default value
edgesDetector.cornersDetectedBlock = {(cornerArray:UnsafeMutablePointer<GLfloat>,cornersDetected:UInt,frameTime:CMTime) -> Void in
self.crosshairGenerator.renderCrosshairsFromArray(cornerArray, count: cornersDetected, frameTime: frameTime)
print("\(cornerArray) =-= \(cornersDetected) =-= \(frameTime)")
}
liveCam.addTarget(edgesDetector)
edgesDetector.addTarget(crosshairGenerator)
crosshairGenerator.addTarget(camView)
liveCam.startCameraCapture()
}
The result :

App crashes when comparing two strings of type NSString

I just just "isEqualToString:" to compare to strings in my iPhone App. The var value is a text and "subInput" is a string out of a text field. Till now everything went well, when the first character of the input field has been the same as the first character of the text. But when they don't fit, the App crashes. When typing in a wrong character after starting well, everything is ok.
subInput = [[NSString alloc] initWithString:[theInput text]];
compare = [[NSString alloc] initWithString:[value substringToIndex:subInput.length]];
if([subInput isEqualToString:compare]){
//Here the app stops working
I also tried to compare the result with "!= 0" or "!= nil" but also didn't work.
ADDITIONAL CODE
if([subInput isEqualToString:compare] != nil){
NSLog(#"any");
if([subInput isEqualToString:value]){
NSLog(#"other");
NSLog(#"well done");
theInput.enabled = FALSE;
lastValid = theInput.text;
theMessage.backgroundColor = [UIColor orangeColor];
theMessage.text = #"WELL DONE!!!!";
theMessage.textColor = [UIColor blackColor];
//save points for remaining seconds
score += seconds*10;
//invalidate counter when typed in all text correct
[count invalidate];
[self newTimer:3.0];
}else{
if(theInput.text.length >= range){
NSLog(#"SCROLLEN");
[theText setSelectedRange:NSMakeRange(range, addRange)];
range += addRange;
}
//NSLog(#"String is ok");
//self.view.backgroundColor = [UIColor blackColor];
lastValid = theInput.text;
theMessage.backgroundColor = [UIColor greenColor];
theMessage.text = #"GO GO GO";
theMessage.textColor = [UIColor whiteColor];
}
} else{
//incrementing the fail var for every wrong letter
fails++;
theInput.text = [#"" stringByAppendingString:lastValid];
theMessage.backgroundColor = [UIColor redColor];
theMessage.text = #"WRONG CHARACTER!!!";
theMessage.textColor = [UIColor whiteColor];
if (grade >= 2) {
seconds -= 2;
}
if(grade == 3){
int actual = theInput.text.length;
actual--;
NSString *shorterString = [theInput.text substringToIndex:actual];
lastValid = shorterString;
theInput.text = shorterString;
}
//change bg-color to iritate the player
self.view.backgroundColor = [UIColor colorWithRed:[self r:255]/255.0 green:[self r:255]/255.0 blue:[self r:255]/255.0 alpha:1];
}
You also need to check that [theInput text] is NOT nil.
subInput = [[NSString alloc] initWithString:[theInput text]];
Docs on [NSString initWithString:(NSString *)aString] are clear that you will get an exception if you attempt to initialize with a nil value.
You need to check and see if value's length is greater than subInput's length. If it is not, you are going out of bounds there.

How to update an object's image in NSMutableArray?

I am trying to set the image of the face down card to the image that the value of the card is. The method in KCCard, image:, returns the image of the card.
- (UIImage *)image:(BOOL)yesOrNo
{
if (!yesOrNo) {
return [UIImage imageNamed:#"back-blue-150-3.png"];
} else {
return [UIImage imageNamed:[NSString stringWithFormat:#"%#-%#-150", [self suitAsString], [self valueAsString]]];
}
}
The code I am using in the deal method is as follows.
int lastDealerX = 437;
//int lastDealerY = 49;
int lastDealerTag = 0;
for (KCCard *aCard in dealerHand) {
if (lastDealerTag == 0) {
KCCardView *cardView = [[KCCardView alloc] initWithFrame:CGRectMake(lastDealerX, 49, 150, 215)];
cardView.backgroundColor = [UIColor blackColor];
cardView.image = [aCard image:NO];
cardView.tag = lastDealerTag;
[self.view addSubview:cardView];
lastDealerTag = lastDealerTag + 1;
lastDealerX = lastDealerX + 42;
} else {
KCCardView *cardView = [[KCCardView alloc] initWithFrame:CGRectMake(lastDealerX, 49, 150, 215)];
cardView.backgroundColor = [UIColor blackColor];
cardView.image = [aCard image:YES];
cardView.tag = lastDealerTag;
[self.view addSubview:cardView];
lastDealerTag = lastDealerTag + 1;
lastDealerX = lastDealerX + 42;
}
}
The KCCardView with tag 0 shows the card face down and the other card is face up. The problem is that when I want the face down card to show, it won't. Here is the show code.
- (IBAction)showCard:(id)sender {
for (UIView *view in self.view.subviews) {
for (KCCard *aCard in dealerHand) {
KCCardView *cardView = (KCCardView *)view;
if (cardView.tag == 0) {
cardView.image = [[dealerHand objectAtIndex:0] image:YES];
}
}
}
}
KCCard is an NSObject, KCCardView is a UIImageView, and dealerHand is an NSMutableArray.
Here is a video showing the build and run: http://aleckazarian.com/misc/Blackjack.mov
Here is the XCode project: http://aleckazarian.com/misc/Blackjack.zip
If you look at the connection in the nib you'll notice that it is connected to
showCard
this is a completely different method to
showCard:
In your class you implement - (IBAction)showCard:(id)sender; therefore you need to break the connection in Interface builder and reconnect it.
Update
The second time I ran your program I got
-[UIRoundedRectButton setImage:]: unrecognized selector sent to instance 0x68612e0
This looks like it's because you are iterating over the view's subviews and checking if 0 == tag. 0 is the default value for tag so essentially mostly every view will respond true unless you have explicitly set the tags to something else. The problem code it
for (UIView *view in self.view.subviews) {
for (KCCard *aCard in dealerHand) {
KCCardView *cardView = (KCCardView *)view;
if (cardView.tag == 0) { // <------- This is the bad check
cardView.image = [((KCCard *)[dealerHand objectAtIndex:0]) image:YES];
}
}
}
To fix this either do one of these (they are in order of my preference - I wouldn't go near 3 or 4 in this case):
Keep a reference to the cardView's in an array
Give the cardView's a non zero tag when they are created
Use respondsToSelector:
Test for the class `[cardView isKindOf:[UIButton class]];
The compiler does not know, what kind of object [dealerHand objectAtIndex:0] is, thus it cannot respond to image:. Try this:
cardView.image = [((KCCard *)[dealerHand objectAtIndex:0]) image:YES];