如何释放objective-c中的内存?
How to release memory in objective-c?
我正在我的 app.Here 中开发一个 Gps 地图概念 我发现我的代码中有内存泄漏 我终于解决了一些内存泄漏 三个内存泄漏即将到来 我不知道如何解决这个问题 请指导我anyone.This 是我的代码库和屏幕截图
https://drive.google.com/file/d/0B14zCKcRh39AWm1QNTFMejNqOGc/view?usp=sharing
https://drive.google.com/file/d/0B14zCKcRh39AcmhyM3R3c1ZrZE0/view?usp=sharing
-(NSArray *)decodePolyLine: (NSMutableString *)encoded {
[encoded replaceOccurrencesOfString:@"\\" withString:@"\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
NSInteger lat=0;
NSInteger lng=0;
while (index < len) {
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[[NSNumber alloc] initWithFloat:lat * 1e-5] autorelease];
NSNumber *longitude = [[[NSNumber alloc] initWithFloat:lng * 1e-5] autorelease];
printf("[%f,", [latitude doubleValue]);
printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]] autorelease];
[array addObject:loc];
}
return array;
}
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:@"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:@"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:@"http://maps.google.com/maps?output=dragdir&saddr=%@&daddr=%@", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSLog(@"api url: %@", apiUrl);
NSError *error;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
NSString* encodedPoints = [apiResponse stringByMatching:@"points:\\"([^\\"]*)\\"" capture:1L] ;
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(void) updateRouteView {
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
(kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast) | (kCGBitmapByteOrderMask & kCGBitmapByteOrderDefault)) ;
CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
CGContextRelease(context);
routeView.image = img;
// CGContextRelease(context);
}
如果使用 ARC,则不需要管理内存。
如果你不这样做,就用[object release]
。
强烈建议您在继续阅读之前阅读 Managing Memory in Objective-C。
对于屏幕截图 #2,您似乎没有释放 CGImageRef 对象。为此,要清理它,您应该使用:
CGImageRelease(image);
...当您使用完 CGImageRef 后。
有关此问题的更多信息(以及它与 CFRelease 的不同之处)可在以下问题中找到:Releasing CGImage (CGImageRef)请注意,即使您使用的是 ARC,在使用任何 C -based API,尤其是当你将它们与一些 Obj-C 对象混合在一起时。
对于第一个屏幕截图和您发布的代码,很难说清楚,因为逻辑非常复杂,但是我建议如果您使用的是 ARC,那么我会质疑是否全部使用 'autorelease'你的初始化器确实是必要的。当我尝试在 ARC 项目中使用 'autorelease' 时,它甚至不允许我: Xcode 给出消息 "ARC forbids explicit message send of 'autorelease'." 您可能想要确认您确实为此打开了 ARC项目。
如果有帮助,这个问题讨论了为您的项目打开 ARC:How to enable/disable ARC in an xcode project?
编辑新添加的屏幕截图
来自 Xcode 的此屏幕截图的错误消息非常清楚地指出了问题出在哪里。当调用 'CGColorSpaceCreateDeviceRGB' 时,这会创建一个您负责显式释放的对象。
如果您查看有关 CGColorSpaceCreateDeviceRGB 的文档,您会发现在文档 'Returns' 描述中也有说明:
因此,您需要在创建 CGContextRef 之前调用 'CGColorSpaceCreateDeviceRGB',并且在使用 CGColorSpaceRelease 完成上下文后需要释放它:
CGColorSpaceRef myColorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGContextRef myContext = CGBitmapContextCreate(...);
...
CGContextRelease(myContext);
CGColorSpaceRelease(myColorSpaceRef);
我正在我的 app.Here 中开发一个 Gps 地图概念 我发现我的代码中有内存泄漏 我终于解决了一些内存泄漏 三个内存泄漏即将到来 我不知道如何解决这个问题 请指导我anyone.This 是我的代码库和屏幕截图
https://drive.google.com/file/d/0B14zCKcRh39AWm1QNTFMejNqOGc/view?usp=sharing
https://drive.google.com/file/d/0B14zCKcRh39AcmhyM3R3c1ZrZE0/view?usp=sharing
-(NSArray *)decodePolyLine: (NSMutableString *)encoded {
[encoded replaceOccurrencesOfString:@"\\" withString:@"\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
NSInteger lat=0;
NSInteger lng=0;
while (index < len) {
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[[NSNumber alloc] initWithFloat:lat * 1e-5] autorelease];
NSNumber *longitude = [[[NSNumber alloc] initWithFloat:lng * 1e-5] autorelease];
printf("[%f,", [latitude doubleValue]);
printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]] autorelease];
[array addObject:loc];
}
return array;
}
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:@"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:@"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:@"http://maps.google.com/maps?output=dragdir&saddr=%@&daddr=%@", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSLog(@"api url: %@", apiUrl);
NSError *error;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
NSString* encodedPoints = [apiResponse stringByMatching:@"points:\\"([^\\"]*)\\"" capture:1L] ;
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(void) updateRouteView {
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
(kCGBitmapAlphaInfoMask & kCGImageAlphaPremultipliedLast) | (kCGBitmapByteOrderMask & kCGBitmapByteOrderDefault)) ;
CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
CGContextRelease(context);
routeView.image = img;
// CGContextRelease(context);
}
如果使用 ARC,则不需要管理内存。
如果你不这样做,就用[object release]
。
强烈建议您在继续阅读之前阅读 Managing Memory in Objective-C。
对于屏幕截图 #2,您似乎没有释放 CGImageRef 对象。为此,要清理它,您应该使用:
CGImageRelease(image);
...当您使用完 CGImageRef 后。
有关此问题的更多信息(以及它与 CFRelease 的不同之处)可在以下问题中找到:Releasing CGImage (CGImageRef)请注意,即使您使用的是 ARC,在使用任何 C -based API,尤其是当你将它们与一些 Obj-C 对象混合在一起时。
对于第一个屏幕截图和您发布的代码,很难说清楚,因为逻辑非常复杂,但是我建议如果您使用的是 ARC,那么我会质疑是否全部使用 'autorelease'你的初始化器确实是必要的。当我尝试在 ARC 项目中使用 'autorelease' 时,它甚至不允许我: Xcode 给出消息 "ARC forbids explicit message send of 'autorelease'." 您可能想要确认您确实为此打开了 ARC项目。
如果有帮助,这个问题讨论了为您的项目打开 ARC:How to enable/disable ARC in an xcode project?
编辑新添加的屏幕截图
来自 Xcode 的此屏幕截图的错误消息非常清楚地指出了问题出在哪里。当调用 'CGColorSpaceCreateDeviceRGB' 时,这会创建一个您负责显式释放的对象。
如果您查看有关 CGColorSpaceCreateDeviceRGB 的文档,您会发现在文档 'Returns' 描述中也有说明:
因此,您需要在创建 CGContextRef 之前调用 'CGColorSpaceCreateDeviceRGB',并且在使用 CGColorSpaceRelease 完成上下文后需要释放它:
CGColorSpaceRef myColorSpaceRef = CGColorSpaceCreateDeviceRGB();
CGContextRef myContext = CGBitmapContextCreate(...);
...
CGContextRelease(myContext);
CGColorSpaceRelease(myColorSpaceRef);