CALayer as SubLayer Not Visible - ios4

I am trying to built an animated circle which would be drawn clockwise until it becomes complete circle as illustrated in iPhone Core Animation - Drawing a Circle
Problem is that CALayer object is not added or build. I tested and saw that it is not accessing my drawInContext:CGContextRef and animatingArc methods.
What so far I have done is:
In AnimateArc.h
#interface AnimateArc : CALayer {
CAShapeLayer *circle;
}
-(void) animatingArc;
#end
In AnimateArc.m
-(void) drawInContext:(CGContextRef)ctx
{
CGFloat radius = 50.0;
circle = [CAShapeLayer layer];
//make a circular shape
circle.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0.0, 0.0, 2 * radius, 2 * radius) cornerRadius:radius].CGPath;
CGPoint centerPoint = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2);
//center the shape in self.view
circle.position = centerPoint;
//configure appearence of circle
circle.fillColor = [UIColor clearColor].CGColor;
circle.strokeColor = [UIColor blackColor].CGColor;
circle.lineWidth = 5;
/*CGPointMake((self.contentsCenter.size.width), (self.contentsCenter.size.height));*/
//path the circle
CGContextAddArc(ctx, centerPoint.x, centerPoint.y, radius, 0.0, 2 * M_PI, 0);
CGContextClosePath(ctx);
//fill it
CGContextSetFillColorWithColor(ctx, [UIColor redColor].CGColor);
CGContextFillPath(ctx); }
///////////////////////////////////////////////////////////////////////
-(void) animatingArc
{
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:#"arcEnd"];
anim.duration = 20.0; //animate over 20 seconds
anim.repeatCount = 1.0; //animate only once
anim.removedOnCompletion = NO; //Reamin there after completion
//animate from start to end
anim.fromValue = [NSNumber numberWithFloat:50.0f];
anim.toValue = [NSNumber numberWithFloat:150.0f];
//experiment with timing to get appearence to look the way you want
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
//add animation to circle
[circle addAnimation:anim forKey:#"animatingArc"];
}
/////////////////////
//needed since key not part of animatable properties
+(BOOL) needsDisplayForKey:(NSString *)key
{
if([key isEqualToString:#"arcEnd"])
return YES;
else
return [super needsDisplayForKey:key];
}
//ensure custom properties copied to presentation layer
-(id) initWithLayer:(id)layer
{
if((self = [super initWithLayer:layer]))
{
if ([layer isKindOfClass:[AnimateArc class]])
{
AnimateArc *other = (AnimateArc *) layer;
[other setNeedsDisplay];
}
}
return self; }
And finally in my viewController,
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view.layer addSublayer:AnimateArcObject];
[AnimateArcObject animatingArc];
}
Apology for bad formatting.... Please can someone tell me what am I doing wrong? I have also doubt that my code can crash at any place after accessing those two functions since I am novice about Core Animation and haven't got any idea that I am in right direction or not.
Any help will be appreciated. Thanks.

From my painful experience with CoreAnimation, you must always set the bounds property of any CALayer you instantiate.
So, you're layer is not showing because you are missing something like:
layer.bounds = CGRectMake(0, 0, width, height);
you should place this as soon as you instantiate the layer, and make it a habit to do so, so you don't fall into it again.
As for your code crashing, sorry. It's too distributed and I am not sure how it's linked together, so I can't help you there.

After little searching, I thought that I am going in wrong direction. So I deleted this AnimateArc file and added new one which is inheriting from UIViewController.
Then in viewDidLoad Method, I wrote the code from this link to create circle and animations using path.
In parent view controller, I added AnimatedArc ViewController's subview. Now its working perfectly :)

Related

UITextView to Mimic UITextField [for basic round corner text field]

I want to have UITextField with multiple lines, after a quick google on this issue I found that I should use TextView so I did switch my code to use UITextView when I want multiple lines. My View still have other one line textField that I want to keep.
To make my TextView looks like TextField, I had to add code to set border and radius, but they look a little bit different on iOS7. Does anyone know:
what is the color for the UITextField border? when both enabled and disabled so I can sent my textview to match it.
what is radius of the corner of TextField.
what is the background color for UITextField when it is disabled[attached picture shows the text field has lighter shade of grey when it is disabled]? so i can set my text view to the same color when i disable user interaction.
If there is away to keep using textfield for multiline text, I am all ears and i switch to use it.
Best Regards,
I use this:
textView.layer.borderColor = [[UIColor colorWithRed:215.0 / 255.0 green:215.0 / 255.0 blue:215.0 / 255.0 alpha:1] CGColor];
textView.layer.borderWidth = 0.6f;
textView.layer.cornerRadius = 6.0f;
little differences in the params make it looks more like UITextField(I hope).
I use this:
#import <QuartzCore/QuartzCore.h>
-(void) textViewLikeTextField:(UITextView*)textView
{
[textView.layer setBorderColor:[[UIColor colorWithRed:212.0/255.0
green:212.0/255.0
blue:212.0/255.0
alpha:1] CGColor]];
[textView.layer setBorderWidth:1.0f];
[textView.layer setCornerRadius:7.0f];
[textView.layer setMasksToBounds:YES];
}
and get a good resut.
I have a small subclass of UITextView that gives in iOS 7 the same look as the UITextField
The interface is empty:
#interface MyTextView : UITextView
#end
The implementation overwrites the initialization and the setter of the 'editable' property:
#implementation MyTextView
//================================================================================
- (id) initWithFrame: (CGRect) frame
{
self = [super initWithFrame:frame];
if (self)
{
[self commonInit];
}
return self;
}
//================================================================================
- (id) initWithCoder: (NSCoder *) aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self commonInit];
}
return self;
}
//================================================================================
- (void) commonInit
{
self.layer.borderWidth = 1.0f;
self.layer.borderColor = [[UIColor colorWithRed:232.0/255.0
green:232.0/255.0 blue:232.0/255.0 alpha:1] CGColor];
self.layer.cornerRadius = 6;
}
//================================================================================
- (void) setEditable: (BOOL) editable
{
[super setEditable:editable];
if (editable)
{
self.backgroundColor = [UIColor whiteColor];
}
else
{
self.backgroundColor = [UIColor colorWithRed:250.0/255.0
green:250.0/255.0 blue:250.0/255.0 alpha:1];
}
}
//================================================================================
#end
This is the closest I got with enabled UITextView
[yourTextView.layer setBorderColor:[[[UIColor lightGrayColor] colorWithAlphaComponent:0.2] CGColor]];
[yourTextView.layer setBorderWidth:2.0];
yourTextView.layer.cornerRadius = 5;
yourTextView.clipsToBounds = YES;
yourTextView.textColor = [UIColor lightGrayColor];

UIGraphicsBeginImageContext created image stays in memory forever

I'm creating many colour variations of an image using Core Graphics. I need to create about 320 in total but gradually, the memory usage of the app keeps increasing until it crashes. From Instruments, I see that more CGImage objects are being created and stay alive. I want to release them because I store the images to the cache directory in PNG format.
I have searched through all other solutions I could find without success. Any help is appreciated. Thanks.
Here's the main part:
+(UIImage *)tintedImageFromImage:(UIImage *)sourceImage colour:(UIColor *)color intensity:(float)intensity {
if (UIGraphicsBeginImageContextWithOptions != NULL) {
UIGraphicsBeginImageContextWithOptions(sourceImage.size, NO, 0.0);
} else {
UIGraphicsBeginImageContext(sourceImage.size);
}
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect rect = CGRectMake(0, 0, sourceImage.size.width, sourceImage.size.height);
// draw alpha-mask
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGContextDrawImage(context, rect, sourceImage.CGImage);
// draw tint color, preserving alpha values of original image
CGContextSetBlendMode(context, kCGBlendModeSourceIn);
[color setFill];
CGContextFillRect(context, rect);
//Set the original greyscale template as the overlay of the new image
sourceImage = [self verticallyFlipImage:sourceImage];
[sourceImage drawInRect:CGRectMake(0,0, sourceImage.size.width,sourceImage.size.height) blendMode:kCGBlendModeMultiply alpha:intensity];
UIImage *colouredImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
colouredImage = [self verticallyFlipImage:colouredImage];
return colouredImage;
}
this is used to flip the image:
+(UIImage *)verticallyFlipImage:(UIImage *)originalImage {
UIImageView *tempImageView = [[UIImageView alloc] initWithImage:originalImage];
UIGraphicsBeginImageContext(tempImageView.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, tempImageView.frame.size.height);
CGContextConcatCTM(context, flipVertical);
[tempImageView.layer renderInContext:context];
UIImage *flippedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return flippedImage;
}
Add to verticallyFlipImage the line tempImageView.image = nil; in order to make the image view release the image. This solves the problem.

iOS4 MKMapKit - map not zooming in when more than one pin

Sure this is something simple as I'm just starting with the maps. I already have a map showing one location, but when I've added a second anotation the map stays zoomed all the way out rather than going to my locations. The pins are there when I zoom in, so I know that bit's working.
Code snippets:
- (void)viewDidLoad
{
...
...
...
// Set coordinates for our position
CLLocationCoordinate2D location;
location.latitude = [self.lat doubleValue];
location.longitude = [self.lon doubleValue];
// Add the annotation to our map view
MapViewAnnotation *newAnnotation = [[MapViewAnnotation alloc]
initWithTitle:self.placename
andSubtitle:self.subtitle
andCoordinate:location];
[self.mapView addAnnotation:newAnnotation];
[newAnnotation release];
// Set coordinates for our second position
CLLocationCoordinate2D amenitylocation;
amenitylocation.latitude = self.latitude;
amenitylocation.longitude = self.longitude;
// Add the annotation to our map view
MapViewAnnotation *amenityAnnotation = [[MapViewAnnotation alloc]
initWithTitle:self.callouttitle
andSubtitle:self.calloutsubtitle
andCoordinate:amenitylocation];
[self.mapView addAnnotation:amenityAnnotation];
[amenityAnnotation release];
[super viewDidLoad];
}
#pragma mark - MKMapView Delegates
// When a map annotation point is added, zoom to it (1500 range)
- (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
{
MKAnnotationView *annotationView = [views objectAtIndex:0];
id <MKAnnotation> mp = [annotationView annotation];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([mp coordinate], 1500, 1500);
[mv setRegion:region animated:YES];
[mv selectAnnotation:mp animated:YES];
}
- (MKAnnotationView *)mapView:(MKMapView *)mv viewForAnnotation:(id<MKAnnotation>)annotation
{
if(mapView.userLocation==annotation)
{
return nil;
}
NSString *identifier = #"IDENTIFIER";
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if(annotationView==nil)
{
annotationView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier]autorelease];
annotationView.pinColor=MKPinAnnotationColorPurple;
annotationView.canShowCallout=YES;
}
return annotationView;
}
I'd appreciate any pointers.
Also, am I right in thinking I'll have to make custom callouts if I want more than one to appear on the map at the same time?
Sorry, found the answer - I didn't have the MKMapView delegate linked to File's Owner in IB, although I do have in my header file. Linked that up and it's working.

Touch events on MKMapView's overlays

In the app I'm currently designing I have a MKMapView with overlays on it (customized MKPolylines btw) and I would like to be able to detect touch events on these overlays and assign a specific action to each overlay. Could any one help me on this one ?
Thanks !
Benja
This can be solved combining How to intercept touches events on a MKMapView or UIWebView objects? and How to determine if an annotation is inside of MKPolygonView (iOS). Add this in viewWillAppear:
WildcardGestureRecognizer * tapInterceptor = [[WildcardGestureRecognizer alloc] init];
tapInterceptor.touchesBeganCallback = ^(NSSet * touches, UIEvent * event) {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.mapView];
CLLocationCoordinate2D coord = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
MKMapPoint mapPoint = MKMapPointForCoordinate(coord);
for (id overlay in self.mapView.overlays)
{
if ([overlay isKindOfClass:[MKPolygon class]])
{
MKPolygon *poly = (MKPolygon*) overlay;
id view = [self.mapView viewForOverlay:poly];
if ([view isKindOfClass:[MKPolygonView class]])
{
MKPolygonView *polyView = (MKPolygonView*) view;
CGPoint polygonViewPoint = [polyView pointForMapPoint:mapPoint];
BOOL mapCoordinateIsInPolygon = CGPathContainsPoint(polyView.path, NULL, polygonViewPoint, NO);
if (mapCoordinateIsInPolygon) {
debug(#"hit!")
} else {
debug(#"miss!");
}
}
}
}
};
[self.mapView addGestureRecognizer:tapInterceptor];
WildcardGestureRecognizer is in the first linked answer. Calling mapView:viewForOverlay: won't be cheap, adding a local cache of those would help.
Just in case it might help some of you...
I couldn't find a way to do that but I added an annotation on my overlays (Anyway, i needed to do that to display some information) and then I could get the touch event on this annotation. I know it is not the best way to do it but in my situation, and maybe yours, it works ;) !

how to bound uiimagegview moving in particular portion

I am working on an application in which I am adding the same image again and again on a button click on random positions and moving those images.
But on moving those images, images can move in whole view inspite of moving in UIView i want my image to move only in subview(UIImage view) on which i am adding it.
here is my code of TouchesMoved
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
UIImageView *imgPimple;// = [[UIImageView alloc]init];
imgPimple = (UIImageView*)[touch view];
CGPoint touchLocation = [touch locationInView:imgPimple superview];
if ([touch.view isKindOfClass:[UIImageView class]])
{
imgPimple.center = touchLocation;
}
}
What you should be doing is:
CGPoint touchLocation = [touch locationInView:[imgPimple superview]];
I think.
It seems to me that if you're deciding where to move it in its superview, and you get the touch location in the imgPimple view, it will behave incorrectly.

Resources