Toll-free bridging and memory management - iphone

My iPhone app needs to do some URL escape sequence encoding for a form parameter. The NSString stringByAddingPercentEscapesUsingEncoding as stringByAddingPercentEscapesUsingEncoding doesn't escape a lot. This is what I have
-(NSString*)currentMessageUrlEncoded{
CFStringRef originalURLString = (CFStringRef) self.currentMessage;
CFStringRef urlString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, originalURLString, NULL, (CFStringRef) #"&+", kCFStringEncodingUTF8);
NSString *result = (NSString*) urlString;
[result autorelease]; // Is this sufficient?
return result;
}
I'm not sure about the memory management here? Is the autorelease on the result sufficient, or am I barking up the wrong tree altogether?

Yes it is. You could even shorten you method a bit:
- (NSString *)urlEncodedMessage:(NSString *)message {
CFStringRef urlString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef) message, NULL, (CFStringRef) #"&+", kCFStringEncodingUTF8);
return [(NSString *)urlString autorelease];
}

Related

Potential leak of an object stored into setting username and setting password value

I am analyzing my application and face Potential leak of an object stored into setting username and setting password value my code is given
-(void) checkRememberPassword{
CFStringRef userNameKey = CFSTR("user_id_preferences");
CFStringRef settingUserName = (CFStringRef)CFPreferencesCopyAppValue(userNameKey, kCFPreferencesCurrentApplication);
CFStringRef passwordKey = CFSTR("password_preferences");
CFStringRef settingPasswordValue = (CFStringRef)CFPreferencesCopyAppValue(passwordKey, kCFPreferencesCurrentApplication);
NSString *tempString = (__bridge NSString *)settingPasswordValue;
NSString *tempString1 = (__bridge NSString *)settingUserName;
if(([tempString1 length] != 0) || ([tempString length] !=0)){
txtUserName.text = (__bridge NSString *)settingUserName;
txtPassword.text = (__bridge NSString *)settingPasswordValue;
[checkBoxButton setImage:[UIImage imageNamed:#"checkbox_full.png"] forState:UIControlStateNormal];
flagForRemPassword = YES;
}
}
The string returned by CFPreferencesCopyAppValue follows the Create rule (https://developer.apple.com/library/ios/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html#//apple_ref/doc/uid/20001148-103029) in Core Foundation -- you need to call CFRelease when you are finished with it. ARC does not do this for you.
Use CFBridgingRelease to transfer ownership of the object to ARC, instead of a simple C-style cast:
NSString *tempString = (NSString*)CFBridgingRelease(settingPasswordValue);

url Encoding in ios

I get a link from server to image has already been Encoding so it comes with %20
But sometimes I get a code include Hebrew characters, so I need to do Encoding agian , With the above code:
But after my Encoding i get in response that % 20 change to % 2520
static CFStringRef charsToEscape = CFSTR("&=");
+ (NSString *)escapeStringByAddingPercentEscapes: (NSString*) string {
return [(NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)string,
NULL,
charsToEscape,
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)) autorelease];
}
i tried to add % to charsToEscape like this:
static CFStringRef charsToEscape = CFSTR("&=%");
but it did not help.
thanks
NSString *urlString = #"----YOUR URL HERE----";
[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlString];
Your idea is good if I did not get the Hebrew characters in the link.
But I found the solution , I just sent the % in the parameter legalURLCharactersToBeEscaped
now i use in the function like this:
static CFStringRef charsToEscape = CFSTR("&=");
static CFStringRef charsUnchanged = CFSTR("%");
+ (NSString *)escapeStringByAddingPercentEscapes: (NSString*) string {
return [(NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)string,
charsUnchanged,
charsToEscape,
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)) autorelease];
}
thanks

Memory leak in iphone App when analyzed

I'm getting a memory leak signal like the one shown in
how can i clear this, please help me .
Use (__bridge_transfer NSString *) instead of (__bridge NSString *)
With ARC, you can use __bridge_transfer to transfer memory management of the returned string to ARC
Example:
NSString *myString = [self encodeURL:#"hi*)"];
NSLog(#"%#",myString);
-(NSString *)encodeURL:(NSString *)string{
NSString *newString = #"";
newString = (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, CFSTR("^%*)*&%$"),CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
return newString;
}
Try this...
NSString *newString = nil;
CFStringRef stringRef = CFURLCreateStringByAddingPercentEscapes(...);
newString = (NSString *)stringRef;
CFRelease(stringRef);
if(newString)
return newString;
Use
return [newString autorelease];
The NSString object newString is got allocated in the function CFURLCreateStringByAddingPercentEscapes.
so the object attaining the retain count of one at this moment. So when you are retuning the retained object you got memory leak signal. We can add the object newString to the autorelease pool so that the os will take care of the memory to release at the right time.
Hope this helps.

iphone+webservice

I have one web service but when i pass multiple word like new erra it will return 0 bytes in NSMutuabledata
my method is like
NSString *url = [NSString stringWithFormat:#"%#?url='%#'&word=%#",apiUrl,self.urlString,searchword];
NSMutableData *Data = [appDelegate initRequestWithPost:url withPostData:nil];
where searchword is new era
Thanks
I think you have to escape the url string. Try using somthing like this.
+(NSString *)escapeURL:(NSString *)text{
CFStringRef tmp=CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)text,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
kCFStringEncodingUTF8 );
NSString * encodedString = (NSString *)tmp;
return encodedString;
}

Make an NSURL with an encoded plus (%2B)

I need to pass a timestamp with a timezone offset in a GET request, e.g.,
2009-05-04T11:22:00+01:00
This looks like a two arguments "2009-05-04T11:22:00" and "01:00" to the receiving PHP script (over which I've no control).
NSURL doesn't encode plus signs, but if I make an NSURL using the string
2009-05-04T11:22:00%2B01:00
the url I end up with contains:
2009-05-04T11:22:00%252B01:00
Any ideas how I can preserve my encoded plus sign or just plain prevent NSURL from encoding anything?
What worked for me was doing the UTF8 conversion, then replacing the + sign with %2B:
NSString *urlString =
[NSString stringWithFormat:#"%#/iphone/push/create?pn[token]=%#&pn[send_at]=%#",
kHTTPURL, appDelegate.deviceAPNToken, [dateTimeToUse description]];
urlString =
[[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
stringByReplacingOccurrencesOfString:#"+" withString:#"%2B"];
The string should be URL encoded.
Here is a category for NSString that will help:
NSString+Additions.h
#interface NSString (Additions)
- (NSString *)stringByURLEncoding;
NSString+Additions.m
#import "NSString+Additions.h"
#implementation NSString (Additions)
- (NSString *)stringByURLEncoding {
return (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
}
Use NSString's stringByAddingPercentEscapesUsingEncoding: method on the text you want to include as an argument.
As its name implies, the method will convert return an auto-released string containing an url-safe version of the receiver.
Thought I may as well provide my workaround as an answer, as I don't think there's a good solution to the original problem.
The plus sign (+) is completely valid in a URL, so my solution was to convert the time to GMT and remove the timezone/DST offset from the string. I'll leave it as an exercise for the reader to determine the value of secondsFromGMT below as, in my case, it's always the same because I'm only interested in timestamps generated by a web server.
NSString *gmtWhen = [[self descriptionWithCalendarFormat:nil
timeZone:[NSTimeZone
timeZoneForSecondsFromGMT:secondsFromGMT
] locale:nil] stringByReplacingOccurrencesOfString:#" +0000" withString:#""];
Solution when using URLComponents (Swift 3):
var params = ["email": "user+ios-default#example.com", "name": "John Brown"]
var components = URLComponents(string: "http://www.example.com")!
components.path = "/login"
components.queryItems = params.map { URLQueryItem(name: $0, value: $1) }
let url_NoFix = components.url!
// http://www.example.com/login?name=John%20Brown&email=user+ios-default#example.com
let cs = CharacterSet(charactersIn: "+").inverted
let q = components.percentEncodedQuery?.addingPercentEncoding(withAllowedCharacters: cs)
components.percentEncodedQuery = q
let url_Fixed = components.url!
// http://www.example.com/login?name=John%20Brown&email=user%2Bios-default#example.com
encode you string by using below code
NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,NULL,(CFStringRef)#"+",kCFStringEncodingUTF8);
this will encode + of you string which will prevent replacement of + by %2b while posting data in post method
To get encoded plus (%2B) (It works with all charcters) use CFURLCreateStringByAddingPercentEscapes as
/**
get parameterized url from url and query parameters.
*/
+(NSString *)getParameterizedUrl:(NSString *)url withParameters:(NSDictionary *)queryDictionary
{
NSMutableArray *mutablePairs = [NSMutableArray array];
for (NSString *key in queryDictionary) {
[mutablePairs addObject:[NSString stringWithFormat:#"%#=%#", CTPercentEscapedQueryStringKeyFromStringWithEncoding(key, NSUTF8StringEncoding), CTPercentEscapedQueryStringValueFromStringWithEncoding(queryDictionary[key], NSUTF8StringEncoding)]];
}
return [[NSString alloc]initWithFormat:#"%#?%#",url,[mutablePairs componentsJoinedByString:#"&"]];
}
static NSString * const kCharactersToBeEscapedInQueryString = #":/?&=;+!##$()',*";
static NSString * CTPercentEscapedQueryStringKeyFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
static NSString * const kCharactersToLeaveUnescapedInQueryStringPairKey = #"[].";
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kCharactersToLeaveUnescapedInQueryStringPairKey, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
}
static NSString * CTPercentEscapedQueryStringValueFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
}
And use in your code as
NSMutableDictionary *params = [[NSMutableDictionary alloc]init];
[params setObject:#"2009-05-04T11:22:00+01:00" forKey:#"timestamp"];
NSString *urlString = [self getParameterizedUrl:#"http://www.example.com" withParameters:params];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];