Reputation: 4727
I have a custom UIView that draws an image in the draw rect method. My problem is UIView wants me to initWithFrame when I allocate the object. The frame of the view needs to be the same as the image size and width. The problem is that I don't get that image size and width until the drawRect method of the view I am creating. Inside the drawRect view changing the UIView's frame to the image dimensions seems to have no effect. So what I want to do is something like this:
MyCustomView *myCustomView = [[MyCustomView alloc] initWithFrame: CGrectMake(0,0,0,0)];
Then inside MyCustomView's drawRect method I want to somehow change the frame of the view to be the frame size of the image I am creating.
How do I get my desired outcome? An no, creating the image before I init my custom view and putting the size dimensions into the initWithFrame is not an option.
This is my current code in the view's drawRect method
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"%@",self.imgName]];
CGSize imgSize = [image size];
CGRect newrect = CGRectMake(self.frame.origin.x, self.frame.origin.y, imgSize.width, imgSize.height);
self.frame = newrect; //This does nothing!!
CGRect imgRect = CGRectMake(0, 0, imgSize.width, imgSize.height);
[image drawInRect:imgRect];
Upvotes: 2
Views: 10198
Reputation: 119242
An no, creating the image before I init my custom view and putting the size dimensions into the initWithFrame is not an option.
I don't understand why that is not an option, but OK. You have a property on your view, self.imgName
. When this is set (which has to be before the image is drawn), you should get the image, work out its size and set your frame at that point.
Upvotes: 0
Reputation: 39296
If you look at the docs for setFrame it says:
This method, in setting the frame rectangle, repositions and resizes the receiver within the coordinate system of its superview. It neither redisplays the receiver nor marks it as needing display. You must do this yourself with display or setNeedsDisplay:.
It will not redisplay - typically after setting the frame you call setNeedsDisplay. but, this highlights your chicken and egg problem. setNeedsDisplay causes drawrect to fire.
Also, as Sulthan pointed out, doing something heavy like loading images in drawRect is not a good idea. It's heavy weight and things like drawRect get called repeatedly on resize etc...
I would either create an init pattern (even though you said not an option), or create a property to set the image and have the image load at that time.
Upvotes: 5
Reputation: 130072
Changing the frame from inside drawRect is... not a very good idea. How would you imagine the system resizes something while it's currently drawing it?
Also loading the image (slow operation) from inside drawRect (can be called often) is not a very good idea. You should load the image when you get the filename and change view frame at that time. And probably using some animation. The user won't expect the view change its size without animation.
And:
And no, creating the image before I init my custom view and putting the size dimensions into the initWithFrame is not an option.
I can't imagine any situation when this is not an option. It's only about how you architecture your code.
Upvotes: 3