Why is UIImage's drawAtPoint throwing an error in this code? - iphone

I am creating custom cell in my iphone aap and I am also adding an image to it but I continue to get error at [image drawatpoint:p];
the error states
*** -[UIImage drawAtPoint:]: message sent to deallocated instance 0x45cb1f0
my code is
-(void)setImage:(UIImage *)i
{
//[image release];
image = i;
[self setNeedsDisplay];
}
- (void)setNeedsDisplay
{
[super setNeedsDisplay];
[contentView setNeedsDisplay];
}
- (void)drawContentView:(CGRect)r
{
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor *backgroundColor = [UIColor yellowColor];
UIColor *textColor = [UIColor blackColor];
if(self.selected)
{
backgroundColor = [UIColor clearColor];
textColor = [UIColor whiteColor];
}
[backgroundColor set];
CGContextFillRect(context, r);
CGPoint p;
p.x = 3;
p.y = 3;
[textColor set];
UIImage *image2 = image;
[image2 drawAtPoint:p];
p.x += 70; // space between words
[text2 drawAtPoint:p withFont:firstTextFont];
//[image release];
}

You do not retain the image in your setter (setImage:). As the error message says, it's gone at the time you try to draw it.

Related

iOS7 custom button become transparent when highlighted

I just create my own custom button that seem like iOS6 and earlier buttons but on iOS7 my CustomButton turn transparent when highlighted.
I have try to set property adjustsImageWhenHighlighted at NO but nothing change, [self setAlpha:1.f] doesn't work either.
Following, my init method:
-(void) baseInit:(CGRect)frame :(CGFloat *)colorsNormal :(CGFloat *)colorsHighlighted :(CGFloat *)colorsDisabled
{
self.layer.borderWidth=1.0f;
self.layer.borderColor=[[UIColor colorWithRed:0.67f green:0.67f blue:0.67f alpha:1.0f] CGColor];
self.layer.cornerRadius=7.0f;
self.clipsToBounds = YES;
UIImage *image = [self generateUIImageWithGradient:frame :colorsNormal];
[self setBackgroundImage:image forState:UIControlStateNormal];
[self setTitleColor:[UIColor colorWithRed:0.22f green:0.33f blue:0.53f alpha:1.0f] forState:UIControlStateNormal];
UIImage *image2 = [self generateUIImageWithGradient:frame :colorsHighlighted];
[self setBackgroundImage:image2 forState:UIControlStateHighlighted];
[self setTitleColor:[UIColor colorWithRed:1.0f green:1.0f blue:1.0f alpha:1.0f] forState:UIControlStateHighlighted];
UIImage *image3 = [self generateUIImageWithGradient:frame :colorsDisabled];
[self setBackgroundImage:image3 forState:UIControlStateDisabled];
}
-(id) generateUIImageWithGradient:(CGRect)frame :(CGFloat *)colors
{
CGSize size = CGSizeMake(frame.size.width, frame.size.height);
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
size_t gradientNumberOfLocations = 2;
CGFloat gradientLocations[2] = {0.0, 1.0};
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorspace, colors, gradientLocations, gradientNumberOfLocations);
CGContextDrawLinearGradient(context, gradient, CGPointMake(0, 0), CGPointMake(0, size.height), 0);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
CGGradientRelease(gradient);
CGColorSpaceRelease(colorspace);
UIGraphicsEndImageContext();
return image;
}
And my method call :
CGFloat colorsNormal [] = {1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f};
CGFloat colorsHighlighted [] = {0.03f,0.55f,0.97f,1.0f,0.0f,0.37f,0.90f,1.0f};
CGFloat colorsDisabled [] = {1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f};
[self baseInit:rect :colorsNormal :colorsHighlighted :colorsDisabled];
That work like a charm on iOS6 and NormalState work on iOS7.
Thanks for your help
Set the button type property to UIButtonTypeCustom seem to work. Problem solved.

Color Overlay UIButton Image

I'm having this issue when trying to overlay a UIButton's Image with a color.
The overlay color is appearing underneath the Image.
Here is the code that I have in my drawRect method (I have subclassed UIButton):
(void)drawRect:(CGRect)rect
{
CGRect bounds = self.imageView.bounds;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextTranslateCTM(context, 0.0, self.imageView.image.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextClipToMask(context, bounds, [self.imageView.image CGImage]);
CGContextFillRect(context, bounds);
}
Any ideas on how to get the red color on top of the Image?
Succeeded with this hacky code:
- (void)drawRect:(CGRect)rect
{
UIImage* img = [self imageForState:UIControlStateNormal];
[self setImage:nil forState:UIControlStateNormal];
CGRect bounds = self.imageView.bounds;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor colorWithRed:1 green:0 blue:0 alpha:0.2].CGColor);
CGContextDrawImage(context, bounds, img.CGImage);
CGContextFillRect(context, bounds);
}
It seems the image is drawn after drawRect so unless you make it nil, it goes on top of whatever you draw there.
This is solution is not final. I'll edit it with what I get to next.
EDIT: The right solution is to add a semi-transparent UIView on top of the image like this:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIView* tintView = [[UIView alloc] initWithFrame:self.bounds];
tintView.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.2];
tintView.userInteractionEnabled = NO;
[self addSubview:tintView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
UIView* tintView = [[UIView alloc] initWithFrame:self.bounds];
tintView.backgroundColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:0.2];
tintView.userInteractionEnabled = NO;
[self addSubview:tintView];
}
return self;
}
Note: you should do this in your UIButton subclass.

Position UILabel in circle

I want to position a UILabel in the center of my Circle but I can't seem to affect the position of the label. I can only seem to affect the position of the label by changing the height of CGRect frame. changing the other values doesn't affect the position at all.
here's my Circle.m code
- (id)initWithFrame:(CGRect)frame radius:(CGFloat)aRadius color:(UIColor*) aColor {
self = [super initWithFrame:frame];
if (self) {
self.opaque = NO;
[self setRadius:aRadius];
[self setColor:aColor];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
NSString *string = #"1";
UIFont* font = [UIFont systemFontOfSize:80];
UILabel *label = [[UILabel alloc] init];
label.text = string;
label.textColor = [UIColor whiteColor];
label.font = font;
CGRect frame = label.frame;
frame = CGRectMake(10, 10, 0, 85);
label.frame = frame;
CGContextRef contextRef = UIGraphicsGetCurrentContext();
[color setFill];
circle = CGRectMake(0, 0, radius, radius);
CGContextAddEllipseInRect(contextRef, circle);
CGContextDrawPath (contextRef, kCGPathFill);
[label drawRect:circle];
}
and my viewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat radius = 70;
CGRect position = CGRectMake(0, 0, radius, radius);
Circle *myCircle = [[Circle alloc] initWithFrame:position radius:radius color:[UIColor redColor]];
[self.view addSubview:myCircle];
}
You should not be allocating new UIViews in drawRect: (and UILabel is a subclass of UIView). There are a few good ways of doing what you want, but none of them involve allocating a new UILabel in drawRect:.
One way is to make your Circle give itself a UILabel subview in its initializer, and center the label in layoutSubviews. Then in drawRect:, you just draw the circle and don't worry about drawing the label's text:
#implementation Circle {
UILabel *_label;
}
#synthesize radius = _radius;
#synthesize color = _color;
- (id)initWithFrame:(CGRect)frame radius:(CGFloat)aRadius color:(UIColor*) aColor {
self = [super initWithFrame:frame];
if (self) {
self.opaque = NO;
[self setRadius:aRadius];
[self setColor:aColor];
_label = [[UILabel alloc] init];
_label.font = [UIFont systemFontOfSize:80];
_label.textColor = [UIColor whiteColor];
_label.text = #"1";
[_label sizeToFit];
[self addSubview:_label];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGSize mySize = self.bounds.size;
_label.center = CGPointMake(mySize.width * 0.5f, mySize.height * 0.5f);
}
- (void)drawRect:(CGRect)rect {
[self.color setFill];
CGSize mySize = self.bounds.size;
CGFloat radius = self.radius;
[[UIBezierPath bezierPathWithOvalInRect:CGRectMake(mySize.width * 0.5f, mySize.height * 0.5f, self.radius, self.radius)] fill];
}

NSString drawInRect:withFont: and Core Text drawing in same Draw Rect

I am looking to draw the string 'Hello World!' twice. Once with NSString's UIStringDrawing category method and once using Core Text. No matter what I try the Core Text version draws way to big. Does anyone have an explanation why?
The complete Implementation of the UIView bare bones UIView subclass I have created is below.
#implementation CTView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.opaque = YES;
self.backgroundColor = [UIColor whiteColor];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef c = UIGraphicsGetCurrentContext();
[[UIColor blackColor] set];
NSString *helloWorld = #"Hello World!";
UIFont *helloWorldFont = [UIFont systemFontOfSize:16];
CGContextSaveGState(c); {
[helloWorld drawInRect:rect
withFont:helloWorldFont];
} CGContextRestoreGState(c);
CGContextSaveGState(c); {
// setting up attributed string of the catagory name to draw with Core Text
NSMutableAttributedString *name = [[NSMutableAttributedString alloc] initWithString:#"P"];
[name setFont:helloWorldFont];
[name setTextColor:[UIColor blackColor]];
// getting frames for the text
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)name);
CFRelease(name);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, rect);
CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
CGPathRelease(path);
CFRelease(framesetter);
// draw the text
CTFrameDraw(textFrame, c);
CFRelease(textFrame);
} CGContextRestoreGState(c);
}
#end

Large UIImage drawinrect extremely slow on selection

I have a custom UITableView cell that sports an Image, and a headline. I used the fast scrolling example of ABTableViewCell from atebits.
It seems when I select the first row (which is my row with the largest image) it takes a considerable amoun of time to highlight the row, and then push the new view controller.
However when I select any of the other rows, with much smaller images, its almost instant.
Ive attempted to draw the picture using CGContextDrawImage and drawInRect but both yield the same results.
- (void)drawContentView:(CGRect)r highlighted:(BOOL)highlighted {
if ([type isEqualToString:#"first"]) {
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor *backgroundColor = [UIColor blackColor];
UIColor *textColor = [UIColor whiteColor];
UIColor *textBackgroundColor = [[UIColor alloc] initWithWhite:0 alpha:.5];
UIColor *highlightColor;
if (highlighted) {
backgroundColor = [UIColor clearColor];
textColor = [UIColor blueColor];
highlightColor = [[UIColor alloc] initWithWhite:0 alpha:.3];
} else {
highlightColor = [UIColor clearColor];
}
[backgroundColor set];
CGContextFillRect(context, r);
[self.picture drawInRect:CGRectMake(0.0, 0.0, 320, 225)];
[textBackgroundColor set];
CGContextFillRect(context, CGRectMake(0, 170, 320, 55));
[textColor set];
[self.title drawInRect:CGRectMake(5, 170, 320, 55) withFont:firstHeadlineFont lineBreakMode:UILineBreakModeWordWrap];
[highlightColor set];
CGContextFillRect(context, r);
} else {
CGContextRef context = UIGraphicsGetCurrentContext();
UIColor *backgroundColor = [UIColor blackColor];
UIColor *textColor = [UIColor blueColor];
if (highlighted) {
backgroundColor = [UIColor clearColor];
textColor = [UIColor whiteColor];
}
[backgroundColor set];
CGContextFillRect(context, r);
CGPoint p;
p.x = 0;
p.y = 0;
[self.picture drawInRect:CGRectMake(0.0, 0.0, 44, 44)];
[textColor set];
p.x += 44 + 6; // space between words
[self.title drawAtPoint:p withFont:[UIFont systemFontOfSize:20]];
}
}
EDIT:
IS there anything I can do to speed this up? I am caching the image and reading it as well.
I realized I was using a very very large version of the image for my first row, I was able to scale it down before I pulled it from the webserver and this vastly improved performance. NOTE: double check your dimensions are not huge. IE: 2184x1456 hahah