我在从NSManagedObject构建电子邮件消息字符串的方法中遇到内存泄漏。该字符串是使用NSString方便方法创建的,因此应自动释放。我错过了什么?下面的代码... Instruments正在标记方法底部附近的buildString的最终出现(请参阅代码中的注释):
-(void)buildEmailMessage {
//check for presence of lat and lon data
BOOL hasStartLatLon = NO;
BOOL hasEndLanLon = NO;
NSString *startLat;
NSString *startLong;
NSString *endLat;
NSString *endLong;
NSString *mapURL;
NSString *finalMapURL;
if( [managedObject valueForKey:@"startLat"] > 0 ){
hasStartLatLon = YES;
startLat = [self formatLatLon:[managedObject valueForKey:@"startLat"]];
startLong= [self formatLatLon:[managedObject valueForKey:@"startLong"]];
}
if( [managedObject valueForKey:@"endLat"] > 0 ) {
hasEndLanLon = YES;
endLat = [self formatLatLon:[managedObject valueForKey:@"endLat"]];
endLong= [self formatLatLon:[managedObject valueForKey:@"endLong"]];
}
// Build strings from managedObject
// Start with the trip info already validated
NSString *tripName = [managedObject valueForKey:@"tripName"];
NSString *intro = [NSString stringWithString:@"Please contact the approriate authorities and provide them with the enclosed information if our party does not return withing 12 hours of the return date shown below. Thanks.
"];
id vStartDate = [managedObject valueForKey:@"startDate"];
NSString *startDate = [NSString stringWithFormat:@"
Start Date: %@", [vStartDate managedObjectValueDisplay]];
id vEndDate = [managedObject valueForKey:@"endDate"];
NSString *endDate = [NSString stringWithFormat:@"
End Date: %@
", [vEndDate managedObjectValueDisplay]];
NSString *startFrom = [NSString stringWithFormat:@"Departing from:
%@", [managedObject valueForKey:@"startFrom"]];
if( hasStartLatLon ){
startFrom = [startFrom stringByAppendingString:@"
"];
startFrom = [startFrom stringByAppendingString:[self getLatLon:@"start"]];
}
startFrom = [startFrom stringByAppendingString:@"
"];
NSString *endAt = [NSString stringWithFormat:@"Returning to:
%@", [managedObject valueForKey:@"endAt"]];
if( hasStartLatLon ){
endAt = [endAt stringByAppendingString:@"
"];
endAt = [endAt stringByAppendingString:[self getLatLon:@"end"]];
}
endAt = [startFrom stringByAppendingString:@"
"];
// Add a link to Google Maps if there is geodata
if (hasStartLatLon || hasEndLanLon) {
if (hasStartLatLon) {
mapURL = [NSString stringWithFormat:@"http://maps.google.com/?q=%@,%@+(%@)&ll=%@,%@&z=14&t=p", startLat, startLong, [managedObject valueForKey:@"startFrom"], startLat, startLong];
} else {
mapURL = [NSString stringWithFormat:@"http://maps.google.com/?q=%@,%@+(%@)&ll=%@,%@&z=14&t=p", endLat, endLong, [managedObject valueForKey:@"endAt"], endLat, endLong];
}
NSString* escapedUrlString =[mapURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"escaped map url = %@", escapedUrlString);
finalMapURL = [NSString stringWithFormat:@"Link to Google Map:
%@", escapedUrlString];
}
NSString *routeInfo = [NSString stringWithFormat:@"Route Information:
%@
", [managedObject valueForKey:@"routeInfo"]];
// Check for vehicle info
BOOL hasVehicleMakeAndModel = NO;
BOOL hasVehicleLicenseNumber = NO;
BOOL hasVehicleState = NO;
NSString *vehicleMakeAndModel = [managedObject valueForKey:@"vehicleMakeAndModel"];
NSString *vehicleLicenseNumber = [managedObject valueForKey:@"vehicleLicenseNumber"];
NSString *vehicleState = [managedObject valueForKey:@"vehicleState"];
if ( vehicleMakeAndModel.length > 0 ) {
hasVehicleMakeAndModel = YES;
}
if ( vehicleLicenseNumber.length > 0 ) {
hasVehicleLicenseNumber = YES;
}
if ( vehicleState.length > 0 ) {
hasVehicleState = YES;
}
//Build the vehicle string
NSString *vehicleString;
if (hasVehicleMakeAndModel || hasVehicleLicenseNumber || hasVehicleState) {
vehicleString = [NSString stringWithString:@"Vehicle Information:
"];
}
if (hasVehicleMakeAndModel) {
vehicleString = [vehicleString stringByAppendingString:@"Make/Model: "];
vehicleString = [vehicleString stringByAppendingString:vehicleMakeAndModel];
vehicleString = [vehicleString stringByAppendingString:@"
"];
}
if (hasVehicleLicenseNumber) {
vehicleString = [vehicleString stringByAppendingString:@"License #: "];
vehicleString = [vehicleString stringByAppendingString:vehicleLicenseNumber];
vehicleString = [vehicleString stringByAppendingString:@"
"];
}
if (hasVehicleState) {
vehicleString = [vehicleString stringByAppendingString:@"State: "];
vehicleString = [vehicleString stringByAppendingString:vehicleState];
}
// Get the NSSet of party members from the managedObject
// and build the party members/emergency contact info
NSSet *membersSet = [managedObject valueForKey:@"members"];
NSString *membersString;
if ( [membersSet count] > 0) {
membersString = @"
Party Members:
";
NSArray *membersArray = [NSArray arrayByOrderingSet:membersSet byKey:@"lastName" ascending:YES];
for (NSManagedObject *oneObject in membersArray) {
BOOL hasFirstName = NO;
BOOL hasLastName = NO;
BOOL hasAge = NO;
BOOL hasContactName = NO;
BOOL hasContactNumber = NO;
NSString *memberFirstName = [oneObject valueForKey:@"firstName"];
NSString *memberLastName = [oneObject valueForKey:@"lastName"];
NSNumber *memberAgeNum = [oneObject valueForKey:@"age"];
NSString *memberAgeString;
if (memberAgeNum > 0) {
memberAgeString = [NSString stringWithFormat:@"%d", [memberAgeNum intValue]];
} else {
memberAgeString = [NSString stringWithString:@""];
}
NSString *contactName = [oneObject valueForKey:@"contactName"];
NSString *contactNumber = [oneObject valueForKey:@"contactNumber"];
if ( [memberFirstName length] > 0) {
hasFirstName = YES;
}
if ( [memberLastName length] > 0) {
hasLastName = YES;
}
if ( [memberAgeString length] > 0) {
hasAge = YES;
}
if ( [contactName length] > 0) {
hasContactName = YES;
}
if ( [contactNumber length] > 0) {
hasContactNumber = YES;
}
NSString *oneMemberString = [NSString stringWithString:@""];
if (hasFirstName) {
oneMemberString = [oneMemberString stringByAppendingFormat:@"%@ ", memberFirstName];
}
if (hasLastName) {
oneMemberString = [oneMemberString stringByAppendingString:memberLastName];
}
if (hasAge) {
oneMemberString = [oneMemberString stringByAppendingFormat:@", %@", memberAgeString];
}
if (hasContactName) {
oneMemberString = [oneMemberString stringByAppendingFormat:@"
Emergency Contact:
%@", contactName];
}
if (hasContactNumber) {
oneMemberString = [oneMemberString stringByAppendingFormat:@"
Phone: %@
", contactNumber];
}
membersString = [membersString stringByAppendingString:oneMemberString];
}
}
NSString *buildString = [NSString stringWithFormat:@"Trip Plan for:
%@
", tripName];
buildString = [buildString stringByAppendingString: intro];
buildString = [buildString stringByAppendingString: startDate];
buildString = [buildString stringByAppendingString: endDate];
buildString = [buildString stringByAppendingString: startFrom];
buildString = [buildString stringByAppendingString: endAt];
if (hasStartLatLon || hasEndLanLon) buildString = [buildString stringByAppendingString: finalMapURL];
buildString = [buildString stringByAppendingString: routeInfo];
// Append the vehicle string if any vehicle data is present
if (hasVehicleMakeAndModel || hasVehicleLicenseNumber || hasVehicleState) {
buildString = [buildString stringByAppendingString: vehicleString];
}
// Append the members string if any members data is present
// **MEMORY LEAK** flagged on the line enclosed by the if statement below
if ( [membersSet count] > 0) {
buildString = [buildString stringByAppendingString: membersString];
}
self.myEmailString = [NSString stringWithString:buildString];
}
-(NSString *)formatLatLon:(NSNumber *)value {
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setPositiveFormat:@"##0.00000"];
NSString *returnString = [formatter stringFromNumber:value];
[formatter release];
return returnString;
}
答案 0 :(得分:2)
您的myEmailString
@property
如何定义?使用copy
或retain
? (您应该将copy
与NSString
个对象一起使用。)如果是这样,并且您没有在[myEmailString release]
中执行dealloc
,则可能是泄密。