The Leaks instrument is sounding the alarm on some code, but I don't know how to address the leak without crashing the app. Here's some code summarizing my approach, written some time ago and clearly in need of rethinking:
labels = [[NSMutableArray alloc] init];
for(int i = 0; i < 10; i++) {
// calculate x and y...
label = [[UILabel alloc] initWithFrame:CGRectMake(x, y, 70, 15)];
// customize label...
[labels addObject:label];
[label release];
[self addSubview:[labels objectAtIndex:i]];
}
Why bother with the labels NSMutableArray? Later, in other methods, I need to change the alpha of the labels, and it's convenient to be able to say
[[labels objectAtIndex:num] setAlpha:0.5];
I believe the leak occurs because labels doesn't get dealloc'ed during the normal app lifecycle, only when the superview is dealloc'd at quit.
Help!
Thanks.
It's probably happening because you're not dealloc'ing the labels array. What about releasing the labels array after the for loop, then using .tag to set the label on the UIView and find the label later via the .tag using viewWithTag to setAlpha?
labels = [[NSMutableArray alloc] init];
for(int i = 0; i < 10; i++) {
// calculate x and y...
label = [[UILabel alloc] initWithFrame:CGRectMake(x, y, 70, 15)];
label.tag = 100;
// customize label...
[labels addObject:label];
[label release];
[self addSubview:[labels objectAtIndex:i]];
}
[labels removeAllObjects];
[labels release];
Then later
(UILabel*) [[self.view viewWithTag:100] setAlpha:0.5];
Related
I have an UIImageView that I am moving around a circle with CGAffineTransformRotate. Works great! But when the user press a stop bottom I would like to the the actual x- / y- position of the UIImageView. So far I am always getting the original x- / y- values from when the UIImageView was created.
Is there a way to get the actual position, when the user stopped the rotation?
I have found the solution and share it in case someone is running a similar case:
From UIBezierPath I use the bounds information and this give me the position where the UIImageView stopped. Here the code:
UIBezierPath *path = [[UIBezierPath alloc] init];
[path addArcWithCenter:CGPointMake(iMiddleX, iMiddleY) radius:flR startAngle:degreesToRadians(flDegrees-0.01) endAngle:degreesToRadians(flDegrees) clockwise:YES];
CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:#"position"];
pathAnimation.calculationMode = kCAAnimationPaced;
pathAnimation.fillMode = kCAFillModeForwards;
pathAnimation.removedOnCompletion = NO;
pathAnimation.repeatCount = 1;
pathAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
pathAnimation.duration = 1.0;
pathAnimation.path = path.CGPath;
NSInteger iX = path.bounds.origin.x;
NSInteger iY = path.bounds.origin.y;
- (void) GetClientRect
NSArray *screenArray = [NSScreen screens];
NSScreen *mainScreen = [NSScreen mainScreen];
unsigned screenCount = [screenArray count];
unsigned index = 0;
for (index; index < screenCount; index++)
{
NSScreen *screen = [screenArray objectAtIndex: index];
NSRect screenRect = [screen visibleFrame];
NSString *mString = ((mainScreen == screen) ? #"Main" : #"not-main");
NSLog(#"Screen #%d (%#) Frame: %#", index, mString, NSStringFromRect(screenRect));
}
}
Above method is use to get frame for mainscreen.
But i want method which return Screen size of NSWindow whose kCGWindowNumber have been passed.
Any idea ?!
Why are you working with a CGWindowID (which is what I assume you meant by kCGWindowNumber)? That's a very unnatural thing to do in most circumstances.
Anyway, you can call CGWindowListCopyWindowInfo(0, theWindowID) and examine the dictionary in the first element of the returned array. Use the key kCGWindowBounds to get a dictionary representation of the bounds rectangle and then CGRectMakeWithDictionaryRepresentation() to convert that to a CGRect.
Are you looking for how to convert the NSWindow -frame, which is in Cocoa's coordinate system, to the Core Graphics coordinate system? The Cocoa coordinate system has its origin at the bottom-left of the primary display, with Y increasing in the up direction. The Core Graphics coordinate system has its origin at the top-left of the primary display, with Y increasing in the down direction.
So, the conversion looks like this:
NSWindow* window = /* ... comes from wherever ... */;
NSRect frame = window.frame;
frame.origin.y = NSMaxY([NSScreen.screens.firstObject frame]) - NSMaxY(frame);
CGRect cgbounds = NSRectToCGRect(frame);
How can I calculate a textfield in a loop? I have a textfield in a loop and I want to calculate the input in another textfield.
x = 36; y = 0; w = 36 h = 25 ;
moretext = 0 ;
for (moretext=0; moretext<5; moretext ++) {
textFiled1 = [[UITextField alloc]initWithFrame:CGRectMake(x, y, w, h)];
textFiled1.textAlignment = NSTextAlignmentCenter;
textFiled1.backgroundColor = [UIColor clearColor];
textFiled1.font = [UIFont fontWithName:#"Helvetica " size:(8)];
x+=36 ;
[self.view addSubview:textFiled1];
}
I want to have the TOTAL for the textfield1 loop input showing in textfield2
textFiled2 = [[UITextField alloc]initWithFrame:CGRectMake(180, 0, 36, 25)];
textFiled2.textAlignment = NSTextAlignmentCenter;
textFiled2.backgroundColor = [UIColor clearColor];
textFiled2.font = [UIFont fontWithName:#"Helvetica " size:(8)];
[self.view addSubview:textFiled2];
Implementing the UITextFieldDelegate protocol you can get updates from the UITextField as people type. textFieldDidEndEditing: will tell you when someone is done editing a textfield as well.
See: http://developer.apple.com/library/ios/#documentation/uikit/reference/UITextFieldDelegate_Protocol/UITextFieldDelegate/UITextFieldDelegate.html
May be you need to revise the code:
At the time of allocating multiple UITextField objects, you need to store these in some array like this.
myArray = [[NSMutableArray alloc]init];
UITextField *textFiled1;
int moretext = 0 ;
for (moretext=0; moretext<5; moretext ++, y=y+50) {
textFiled1 = [[UITextField alloc]initWithFrame:CGRectMake(x, y, w, h)];
textFiled1.textAlignment = NSTextAlignmentCenter;
textFiled1.backgroundColor = [UIColor blueColor];
textFiled1.font = [UIFont fontWithName:#"Helvetica " size:(8)];
textFiled1.text = [NSString stringWithFormat:#"%d",y];
//x+=36 ;
[myArray addObject:textFiled1];
[self.view addSubview:textFiled1];
NSLog(#"view Did Load called");
}
Later to do the total you need to traverse through array and extract the text field value and accumulate in some variable like this.
- (int) calc {
int total=0;
int counter;
for (counter=0; counter<5; counter ++) {
UITextField *field1 = [myArray objectAtIndex:counter];
total = total + [field1.text intValue];
NSLog(#"value: %d",[field1.text intValue]);
}
return total;
}
I'm programmatically creating labels in a function and putting them into an NSMutableArray, then I delete them from another function.
The problem is that the labels actually disappear from screen but they're still using memory and when some time passes the program starts to work very slow.
Here is my code:
This is the function that creates the labels.
- (void)CrearEstrellas{
for(int i=0; i< 10; i++)
{
float x = arc4random() %300;
float y = arc4random() %100;
UILabel *estrella = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, 4, 4)];
estrella.tag = i;
estrella.center = CGPointMake(x,y-100);
estrella.text = #".";
estrella.textColor = [UIColor whiteColor];
[self.view.superview addSubview: estrella];
[arrayEstrellas insertObject:(estrella) atIndex: i];
}
}
And this is the function that delete them from the superview:
- (void)Lineatiempo{
for(int i=0; i<[arrayEstrellas count]; i++)
{
UILabel *estrella = [arrayEstrellas objectAtIndex:(i)];
float x = estrella.center.x;
float y = estrella.center.y;
estrella.center = CGPointMake(x,y+10);
if(estrella.center.y>200){
[estrella removeFromSuperview];
estrella = nil;
}
}
}
I would like to know what am i doing wrong! Thanks.
You add the view to an array. NSArray (and NSMutableArray) retain the objects you add to them. The aren't deallocated until you remove them from the array.
So in addition to calling removeFromSuperview you also have to remove the view from the array.
Greetings,
I'm trying to draw a circle on a map. all the separate pieces of this project work independently but when I put them all together it breaks.
I setup my UI in my viewDidLoad, retaining most of it.
I then use touch events to call a my refresh map method:
-(void)refreshMap{
NSString *thePath = [NSString stringWithFormat:#"http://maps.google.com/staticmap?center=%f,%f&zoom=%i&size=640x640&maptype=hybrid",viewLatitude, viewLongitude, zoom];
NSURL *url = [NSURL URLWithString:thePath];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *mapImage = [[UIImage alloc] initWithData:data];
mapImage = [self addCircle:(mapImage) influence:(70) latCon:(320) lonCon:(320)];
NSLog(#"-- mapimageview retaincount %i",[mapImage retainCount]);
mapImageView.image = mapImage;
[mapImage release];}
Setup like this it will load the map with a circle once, but if the map is refreshed again it crashes.
If I comment out the mapImage release it works repeatedly but causes a memory leak.
The addCircle method I'm using:
-(UIImage *)addCircle:(UIImage *)img radius:(CGFloat)radius latCon:(CGFloat)lat lonCon:(CGFloat)lon{
int w = img.size.width;
int h = img.size.height;
lon = h - lon;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL, w, h, 8, 4 * w, colorSpace, kCGImageAlphaPremultipliedFirst);
//draw the circle
CGContextDrawImage(context, CGRectMake(0, 0, w, h), img.CGImage);
CGRect leftOval = {lat- radius/2, lon - radius/2, radius, radius};
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 0.3);
CGContextAddEllipseInRect(context, leftOval);
CGContextFillPath(context);
CGImageRef imageMasked = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
return [UIImage imageWithCGImage:imageMasked];}
Any insight/advise is greatly appreciated!
UIImage *mapImage = [[UIImage alloc] initWithData:data];
mapImage = [self addCircle:(mapImage) influence:(70) latCon:(320) lonCon:(320)];
That's not good. You're losing the reference to the contents of mapImage when you reassign it on the second line. The easiest way to fix this if probably to just add an additional variable, so you can keep track of both images.