How do I URL encode a string - ios

I have a URL string (NSString) with spaces and & characters. How do I url encode the entire string (including the & ampersand character and spaces)?

Unfortunately, stringByAddingPercentEscapesUsingEncoding doesn't always work 100%. It encodes non-URL characters but leaves the reserved characters (like slash / and ampersand &) alone. Apparently this is a bug that Apple is aware of, but since they have not fixed it yet, I have been using this category to url-encode a string:
#implementation NSString (NSString_Extended)
- (NSString *)urlencode {
NSMutableString *output = [NSMutableString string];
const unsigned char *source = (const unsigned char *)[self UTF8String];
int sourceLen = strlen((const char *)source);
for (int i = 0; i < sourceLen; ++i) {
const unsigned char thisChar = source[i];
if (thisChar == ' '){
[output appendString:#"+"];
} else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' ||
(thisChar >= 'a' && thisChar <= 'z') ||
(thisChar >= 'A' && thisChar <= 'Z') ||
(thisChar >= '0' && thisChar <= '9')) {
[output appendFormat:#"%c", thisChar];
} else {
[output appendFormat:#"%%%02X", thisChar];
}
}
return output;
}
Used like this:
NSString *urlEncodedString = [#"SOME_URL_GOES_HERE" urlencode];
// Or, with an already existing string:
NSString *someUrlString = #"someURL";
NSString *encodedUrlStr = [someUrlString urlencode];
This also works:
NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8 );
Some good reading about the subject:
Objective-c iPhone percent encode a string?
Objective-C and Swift URL encoding
http://cybersam.com/programming/proper-url-percent-encoding-in-ios
https://devforums.apple.com/message/15674#15674
http://simonwoodside.com/weblog/2009/4/22/how_to_really_url_encode/

This might be helpful
NSString *sampleUrl = #"http://www.google.com/search.jsp?params=Java Developer";
NSString* encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding];
For iOS 7+, the recommended way is:
NSString* encodedUrl = [sampleUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
You can choose the allowed character set as per the requirement of the URL component.

New APIs have been added since the answer was selected; You can now use NSURLUtilities. Since different parts of URLs allow different characters, use the applicable character set. The following example encodes for inclusion in the query string:
encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
To specifically convert '&', you'll need to remove it from the url query set or use a different set, as '&' is allowed in a URL query:
NSMutableCharacterSet *chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;
[chars removeCharactersInRange:NSMakeRange('&', 1)]; // %26
encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:chars];

Swift 2.0 Example (iOS 9 Compatiable)
extension String {
func stringByURLEncoding() -> String? {
let characters = NSCharacterSet.URLQueryAllowedCharacterSet().mutableCopy() as! NSMutableCharacterSet
characters.removeCharactersInString("&")
guard let encodedString = self.stringByAddingPercentEncodingWithAllowedCharacters(characters) else {
return nil
}
return encodedString
}
}

ios 7 update
NSString *encode = [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *decode = [encode stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

Here's a production-ready flexible approach in Swift 5.x:
public extension CharacterSet {
static let urlQueryParameterAllowed = CharacterSet.urlQueryAllowed.subtracting(CharacterSet(charactersIn: "&?"))
static let urlQueryDenied = CharacterSet.urlQueryAllowed.inverted()
static let urlQueryKeyValueDenied = CharacterSet.urlQueryParameterAllowed.inverted()
static let urlPathDenied = CharacterSet.urlPathAllowed.inverted()
static let urlFragmentDenied = CharacterSet.urlFragmentAllowed.inverted()
static let urlHostDenied = CharacterSet.urlHostAllowed.inverted()
static let urlDenied = CharacterSet.urlQueryDenied
.union(.urlQueryKeyValueDenied)
.union(.urlPathDenied)
.union(.urlFragmentDenied)
.union(.urlHostDenied)
func inverted() -> CharacterSet {
var copy = self
copy.invert()
return copy
}
}
public extension String {
func urlEncoded(denying deniedCharacters: CharacterSet = .urlDenied) -> String? {
return addingPercentEncoding(withAllowedCharacters: deniedCharacters.inverted())
}
}
Example usage:
print("Hello, World!".urlEncoded()!)
print("You&Me?".urlEncoded()!)
print("#Blessed 100%".urlEncoded()!)
print("Pride and Prejudice".urlEncoded(denying: .uppercaseLetters)!)
Output:
Hello,%20World!
You%26Me%3F
%23Blessed%20100%25
%50ride and %50rejudice

I opted to use the CFURLCreateStringByAddingPercentEscapes call as given by accepted answer, however in newest version of XCode (and IOS), it resulted in an error, so used the following instead:
NSString *apiKeyRaw = #"79b|7Qd.jW=])(fv|M&W0O|3CENnrbNh4}2E|-)J*BCjCMrWy%dSfGs#A6N38Fo~";
NSString *apiKey = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)apiKeyRaw, NULL, (CFStringRef)#"!*'();:#&=+$,/?%#[]", kCFStringEncodingUTF8));

This code helped me for encoding special characters
NSString* encPassword = [password stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]];

Try to use stringByAddingPercentEncodingWithAllowedCharacters method with [NSCharacterSet URLUserAllowedCharacterSet] it will cover all the cases
Objective C
NSString *value = #"Test / Test";
value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLUserAllowedCharacterSet]];
swift
var value = "Test / Test"
value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLUserAllowedCharacterSet())
Output
Test%20%2F%20Test

After reading all the answers for this topic and the (wrong) accepted one, I want to add my contribution.
IF the target is iOS7+, and in 2017 it should since XCode makes really hard to deliver compatibility under iOS8, the best way, thread safe, fast, amd will full UTF-8 support to do this is:
(Objective C code)
#implementation NSString (NSString_urlencoding)
- (NSString *)urlencode {
static NSMutableCharacterSet *chars = nil;
static dispatch_once_t pred;
if (chars)
return [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
// to be thread safe
dispatch_once(&pred, ^{
chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;
[chars removeCharactersInString:#"!*'();:#&=+$,/?%#[]"];
});
return [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
}
#end
This will extend NSString, will exclude RFC forbidden characters, support UTF-8 characters, and let you use things like:
NSString *myusername = "I'm[evil]&want(to)break!!!$->àéìòù";
NSLog(#"Source: %# -> Dest: %#", myusername, [myusername urlencode]);
That will print on your debug console:
Source: I'm[evil]&want(to)break!!!$->àéìòù -> Dest: I%27m%5Bevil%5D%26want%28to%29break%21%21%21%24-%3E%C3%A0%C3%A9%C3%AC%C3%B2%C3%B9
... note also the use of dispatch_once to avoid multiple initializations in multithread environments.

Apple's advice, in the 10.11 release notes, is:
If you need to percent-encode an entire URL string, you can use this code to encode a NSString intended to be a URL (in urlStringToEncode):
NSString *percentEncodedURLString =
[[NSURL URLWithDataRepresentation:[urlStringToEncode dataUsingEncoding:NSUTF8StringEncoding] relativeToURL:nil] relativeString];

swift code based on chown's objc answer in this thread.
extension String {
func urlEncode() -> String {
return CFURLCreateStringByAddingPercentEscapes(
nil,
self,
nil,
"!*'();:#&=+$,/?%#[]",
CFStringBuiltInEncodings.UTF8.rawValue
)
}
}

Use NSURLComponents to encode HTTP GET parameters:
var urlComponents = NSURLComponents(string: "https://www.google.de/maps/")!
urlComponents.queryItems = [
NSURLQueryItem(name: "q", value: String(51.500833)+","+String(-0.141944)),
NSURLQueryItem(name: "z", value: String(6))
]
urlComponents.URL // returns https://www.google.de/maps/?q=51.500833,-0.141944&z=6
http://www.ralfebert.de/snippets/ios/encoding-nsurl-get-parameters/

In swift 3:
// exclude alpha and numeric == "full" encoding
stringUrl = stringUrl.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!;
// exclude hostname and symbols &,/ and etc
stringUrl = stringUrl.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!;

In Swift 3, please try out below:
let stringURL = "YOUR URL TO BE ENCODE";
let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(encodedURLString)
Since, stringByAddingPercentEscapesUsingEncoding encodes non URL characters but leaves the reserved characters (like !*'();:#&=+$,/?%#[]), You can encode the url like the following code:
let stringURL = "YOUR URL TO BE ENCODE";
let characterSetTobeAllowed = (CharacterSet(charactersIn: "!*'();:#&=+$,/?%#[] ").inverted)
if let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: characterSetTobeAllowed) {
print(encodedURLString)
}

In my case where the last component was Arabic letters I did the following in Swift 2.2:
extension String {
func encodeUTF8() -> String? {
//If I can create an NSURL out of the string nothing is wrong with it
if let _ = NSURL(string: self) {
return self
}
//Get the last component from the string this will return subSequence
let optionalLastComponent = self.characters.split { $0 == "/" }.last
if let lastComponent = optionalLastComponent {
//Get the string from the sub sequence by mapping the characters to [String] then reduce the array to String
let lastComponentAsString = lastComponent.map { String($0) }.reduce("", combine: +)
//Get the range of the last component
if let rangeOfLastComponent = self.rangeOfString(lastComponentAsString) {
//Get the string without its last component
let stringWithoutLastComponent = self.substringToIndex(rangeOfLastComponent.startIndex)
//Encode the last component
if let lastComponentEncoded = lastComponentAsString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.alphanumericCharacterSet()) {
//Finally append the original string (without its last component) to the encoded part (encoded last component)
let encodedString = stringWithoutLastComponent + lastComponentEncoded
//Return the string (original string/encoded string)
return encodedString
}
}
}
return nil;
}
}
usage:
let stringURL = "http://xxx.dev.com/endpoint/nonLatinCharacters"
if let encodedStringURL = stringURL.encodeUTF8() {
if let url = NSURL(string: encodedStringURL) {
...
}
}

-(NSString *)encodeUrlString:(NSString *)string {
return CFBridgingRelease(
CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(__bridge CFStringRef)string,
NULL,
CFSTR("!*'();:#&=+$,/?%#[]"),
kCFStringEncodingUTF8)
);
}
according to the following blog

So many answers but didn't work for me, so I tried the following:
fun simpleServiceCall(for serviceUrl: String, appendToUrl: String) {
let urlString: String = serviceUrl + appendToUrl.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)!
let finalUrl = URL(string: urlString)!
//continue to execute your service call...
}
Hopefully it'll help someone. thanks

For individual www form-encoded query parameters, I made a category on NSString:
- (NSString*)WWWFormEncoded{
NSMutableCharacterSet *chars = NSCharacterSet.alphanumericCharacterSet.mutableCopy;
[chars addCharactersInString:#" "];
NSString* encodedString = [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
encodedString = [encodedString stringByReplacingOccurrencesOfString:#" " withString:#"+"];
return encodedString;
}

//This is without test
NSMutableCharacterSet* set = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
[set addCharactersInString:#"-_.~"];
NSString *encode = [test stringByAddingPercentEncodingWithAllowedCharacters:set];

I faced a similar problem passing complex strings as a POST parameter. My strings can contain Asian characters, spaces, quotes and all sorts of special characters. The solution I eventually found was to convert my string into the matching series of unicodes, e.g. "Hu0040Hu0020Hu03f5...." using [NSString stringWithFormat:#"Hu%04x",[string characterAtIndex:i]] to get the Unicode from each character in the original string. The same can be done in Java.
This string can be safely passed as a POST parameter.
On the server side (PHP), I change all the "H" to "\" and I pass the resulting string to json_decode. Final step is to escape single quotes before storing the string into MySQL.
This way I can store any UTF8 string on my server.

This one is working for me.
func stringByAddingPercentEncodingForFormData(plusForSpace: Bool=false) -> String? {
let unreserved = "*-._"
let allowed = NSMutableCharacterSet.alphanumericCharacterSet()
allowed.addCharactersInString(unreserved)
if plusForSpace {
allowed.addCharactersInString(" ")
}
var encoded = stringByAddingPercentEncodingWithAllowedCharacters(allowed)
if plusForSpace {
encoded = encoded?.stringByReplacingOccurrencesOfString(" ",
withString: "+")
}
return encoded
}
I found the above function from this link: http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/
You can also use this function with swift extension. Please let me know if there is any issue.

For the php function urlencode encoding a NSString to a cString with UTF8Encode, like [NSString UTF8String] was not working.
Here is my custom objective c NSString+ASCIIencode Category with works with all ASCII values 0..255
Header
#import <Cocoa/Cocoa.h>
#interface NSString (ASCIIEncode)
- (const char*)ASCIIEncode;
#end
Implementation
#import "NSString+ASCIIEncode.h"
#implementation NSString (ASCIIEncode)
- (const char*)ASCIIEncode {
static char output[1024];
// https://tools.piex.at/ascii-tabelle/
// https://www.ionos.de/digitalguide/server/knowhow/ascii-american-standard-code-for-information-interchange/
NSMutableArray *ascii = [NSMutableArray new];
// Hex
// 000 Dez Hex
[ascii addObject:#"\0"]; // 000 000 NUL
[ascii addObject:#( 1)]; // 001 001 SOH
[ascii addObject:#( 2)]; // 002 002 STX
[ascii addObject:#( 3)]; // 003 003 ETX
[ascii addObject:#( 4)]; // 004 004 EOT
[ascii addObject:#( 5)]; // 005 005 ENQ
[ascii addObject:#( 6)]; // 006 006 ACK
[ascii addObject:#"\a"]; // 007 007 BEL
[ascii addObject:#"\b"]; // 008 008 BS
[ascii addObject:#( 9)]; // 009 009 TAB
[ascii addObject:#"\n"]; // 010 00A LF
[ascii addObject:#(11)]; // 011 00B VT
[ascii addObject:#(12)]; // 012 00C FF
[ascii addObject:#"\r"]; // 013 00D CR
[ascii addObject:#(14)]; // 014 00E SO
[ascii addObject:#(15)]; // 015 00F NAK
// 010
[ascii addObject:#(16)]; // 016 010 DLE
[ascii addObject:#(17)]; // 017 011 DC1
[ascii addObject:#(18)]; // 018 012 DC2
[ascii addObject:#(19)]; // 019 013 DC3
[ascii addObject:#(20)]; // 020 014 DC4
[ascii addObject:#(21)]; // 021 015 NAK
[ascii addObject:#(22)]; // 022 016 SYN
[ascii addObject:#(23)]; // 023 017 ETB
[ascii addObject:#(24)]; // 024 018 CAN
[ascii addObject:#(25)]; // 025 019 EM
[ascii addObject:#(26)]; // 026 01A SUB
[ascii addObject:#(27)]; // 027 01B ESC
[ascii addObject:#(28)]; // 028 01C FS
[ascii addObject:#(29)]; // 029 01D GS
[ascii addObject:#(30)]; // 030 01E RS
[ascii addObject:#(31)]; // 031 01F US
// 020
[ascii addObject:#" "]; // 032 020 Space
[ascii addObject:#"!"]; // 033 021
[ascii addObject:#"\""]; // 034 022
[ascii addObject:#"#"]; // 035 023
[ascii addObject:#"$"]; // 036 024
[ascii addObject:#"%"]; // 037 025
[ascii addObject:#"&"]; // 038 026
[ascii addObject:#"'"]; // 039 027
[ascii addObject:#"("]; // 040 028
[ascii addObject:#")"]; // 041 029
[ascii addObject:#"*"]; // 042 02A
[ascii addObject:#"+"]; // 043 02B
[ascii addObject:#","]; // 044 02C
[ascii addObject:#"-"]; // 045 02D
[ascii addObject:#"."]; // 046 02E
[ascii addObject:#"/"]; // 047 02F
// 030
[ascii addObject:#"0"]; // 048 030
[ascii addObject:#"1"]; // 049 031
[ascii addObject:#"2"]; // 050 032
[ascii addObject:#"3"]; // 051 033
[ascii addObject:#"4"]; // 052 034
[ascii addObject:#"5"]; // 053 035
[ascii addObject:#"6"]; // 054 036
[ascii addObject:#"7"]; // 055 037
[ascii addObject:#"8"]; // 056 038
[ascii addObject:#"9"]; // 057 039
[ascii addObject:#":"]; // 058 03A
[ascii addObject:#";"]; // 059 03B
[ascii addObject:#"<"]; // 060 03C
[ascii addObject:#"="]; // 061 03D
[ascii addObject:#">"]; // 062 03E
[ascii addObject:#"?"]; // 063 03F
// 040
[ascii addObject:#"#"]; // 064 040
[ascii addObject:#"A"]; // 065 041
[ascii addObject:#"B"]; // 066 042
[ascii addObject:#"C"]; // 067 043
[ascii addObject:#"D"]; // 068 044
[ascii addObject:#"E"]; // 069 045
[ascii addObject:#"F"]; // 070 046
[ascii addObject:#"G"]; // 071 047
[ascii addObject:#"H"]; // 072 048
[ascii addObject:#"I"]; // 073 049
[ascii addObject:#"J"]; // 074 04A
[ascii addObject:#"K"]; // 075 04B
[ascii addObject:#"L"]; // 076 04C
[ascii addObject:#"M"]; // 077 04D
[ascii addObject:#"N"]; // 078 04E
[ascii addObject:#"O"]; // 079 04F
// 050
[ascii addObject:#"P"]; // 080 050
[ascii addObject:#"Q"]; // 081 051
[ascii addObject:#"R"]; // 082 052
[ascii addObject:#"S"]; // 083 053
[ascii addObject:#"T"]; // 084 054
[ascii addObject:#"U"]; // 085 055
[ascii addObject:#"V"]; // 086 056
[ascii addObject:#"W"]; // 087 057
[ascii addObject:#"X"]; // 088 058
[ascii addObject:#"Y"]; // 089 059
[ascii addObject:#"Z"]; // 090 05A
[ascii addObject:#"["]; // 091 05B
[ascii addObject:#"\\"]; // 092 05C
[ascii addObject:#"]"]; // 093 05D
[ascii addObject:#"^"]; // 094 05E
[ascii addObject:#"_"]; // 095 05F
// 060
[ascii addObject:#"`"]; // 096 060
[ascii addObject:#"a"]; // 097 061
[ascii addObject:#"b"]; // 098 062
[ascii addObject:#"c"]; // 099 063
[ascii addObject:#"d"]; // 100 064
[ascii addObject:#"e"]; // 101 065
[ascii addObject:#"f"]; // 102 066
[ascii addObject:#"g"]; // 103 067
[ascii addObject:#"h"]; // 104 068
[ascii addObject:#"i"]; // 105 069
[ascii addObject:#"j"]; // 106 06A
[ascii addObject:#"k"]; // 107 06B
[ascii addObject:#"l"]; // 108 06C
[ascii addObject:#"m"]; // 109 06D
[ascii addObject:#"n"]; // 110 06E
[ascii addObject:#"o"]; // 111 06F
// 070
[ascii addObject:#"p"]; // 112 070
[ascii addObject:#"q"]; // 113 071
[ascii addObject:#"r"]; // 114 072
[ascii addObject:#"s"]; // 115 073
[ascii addObject:#"t"]; // 116 074
[ascii addObject:#"u"]; // 117 075
[ascii addObject:#"v"]; // 118 076
[ascii addObject:#"w"]; // 119 077
[ascii addObject:#"x"]; // 120 078
[ascii addObject:#"y"]; // 121 079
[ascii addObject:#"z"]; // 122 07A
[ascii addObject:#"{"]; // 123 07B
[ascii addObject:#"|"]; // 124 07C
[ascii addObject:#"}"]; // 125 07D
[ascii addObject:#"~"]; // 126 07E
[ascii addObject:#(127)];// 127 07F DEL
// 080
[ascii addObject:#"€"]; // 128 080
[ascii addObject:#(129)];// 129 081
[ascii addObject:#"‚"]; // 130 082
[ascii addObject:#"ƒ"]; // 131 083
[ascii addObject:#"„"]; // 132 084
[ascii addObject:#"…"]; // 133 085
[ascii addObject:#"†"]; // 134 086
[ascii addObject:#"‡"]; // 135 087
[ascii addObject:#"ˆ"]; // 136 088
[ascii addObject:#"‰"]; // 137 089
[ascii addObject:#"Š"]; // 138 08A
[ascii addObject:#"‹"]; // 139 08B
[ascii addObject:#"Œ"]; // 140 08C
[ascii addObject:#(141)];// 141 08D
[ascii addObject:#"Ž"]; // 142 08E
[ascii addObject:#(143)]; // 143 08F
// 090
[ascii addObject:#(144)];// 144 090
[ascii addObject:#"‘"]; // 145 091
[ascii addObject:#"’"]; // 146 092
[ascii addObject:#"“"]; // 147 093
[ascii addObject:#"”"]; // 148 094
[ascii addObject:#"•"]; // 149 095
[ascii addObject:#"–"]; // 150 096
[ascii addObject:#"—"]; // 151 097
[ascii addObject:#"˜"]; // 152 098
[ascii addObject:#"™"]; // 153 099
[ascii addObject:#"š"]; // 154 09A
[ascii addObject:#"›"]; // 155 09B
[ascii addObject:#"œ"]; // 156 09C
[ascii addObject:#(157)];// 157 09D
[ascii addObject:#"ž"]; // 158 09E
[ascii addObject:#"Ÿ"]; // 159 09F
// 0A0
[ascii addObject:#(160)];// 160 0A0
[ascii addObject:#"¡"]; // 161 0A1
[ascii addObject:#"¢"]; // 162 0A2
[ascii addObject:#"£"]; // 163 0A3
[ascii addObject:#"¤"]; // 164 0A4
[ascii addObject:#"¥"]; // 165 0A5
[ascii addObject:#"¦"]; // 166 0A6
[ascii addObject:#"§"]; // 167 0A7
[ascii addObject:#"¨"]; // 168 0A8
[ascii addObject:#"©"]; // 169 0A9
[ascii addObject:#"ª"]; // 170 0AA
[ascii addObject:#"«"]; // 171 0AB
[ascii addObject:#"¬"]; // 172 0AC
[ascii addObject:#(173)];// 173 0AD
[ascii addObject:#"®"]; // 174 0AE
[ascii addObject:#"¯"]; // 175 0AF
// 0B0
[ascii addObject:#"°"]; // 176 0B0
[ascii addObject:#"±"]; // 177 0B1
[ascii addObject:#"²"]; // 178 0B2
[ascii addObject:#"³"]; // 179 0B3
[ascii addObject:#"´"]; // 180 0B4
[ascii addObject:#"µ"]; // 181 0B5
[ascii addObject:#"¶"]; // 182 0B6
[ascii addObject:#"·"]; // 183 0B7
[ascii addObject:#"¸"]; // 184 0B8
[ascii addObject:#"¹"]; // 185 0B9
[ascii addObject:#"º"]; // 186 0BA
[ascii addObject:#"»"]; // 187 0BB
[ascii addObject:#"¼"]; // 188 0BC
[ascii addObject:#"½"]; // 189 0BD
[ascii addObject:#"¾"]; // 190 0BE
[ascii addObject:#"¿"]; // 191 0BF
// 0C0
[ascii addObject:#"À"]; // 192 0C0
[ascii addObject:#"Á"]; // 193 0C1
[ascii addObject:#"Â"]; // 194 0C2
[ascii addObject:#"Ã"]; // 195 0C3
[ascii addObject:#"Ä"]; // 196 0C4
[ascii addObject:#"Å"]; // 197 0C5
[ascii addObject:#"Æ"]; // 198 0C6
[ascii addObject:#"Ç"]; // 199 0C7
[ascii addObject:#"È"]; // 200 0C8
[ascii addObject:#"É"]; // 201 0C9
[ascii addObject:#"Ê"]; // 202 0CA
[ascii addObject:#"Ë"]; // 203 0CB
[ascii addObject:#"Ì"]; // 204 0CC
[ascii addObject:#"Í"]; // 205 0CD
[ascii addObject:#"Î"]; // 206 0CE
[ascii addObject:#"Ï"]; // 207 0CF
// 0D0
[ascii addObject:#"Ð"]; // 208 0D0
[ascii addObject:#"Ñ"]; // 209 0D1
[ascii addObject:#"Ò"]; // 210 0D2
[ascii addObject:#"Ó"]; // 211 0D3
[ascii addObject:#"Ô"]; // 212 0D4
[ascii addObject:#"Õ"]; // 213 0D5
[ascii addObject:#"Ö"]; // 214 0D6
[ascii addObject:#"×"]; // 215 0D7
[ascii addObject:#"Ø"]; // 216 0D8
[ascii addObject:#"Ù"]; // 217 0D9
[ascii addObject:#"Ú"]; // 218 0DA
[ascii addObject:#"Û"]; // 219 0DB
[ascii addObject:#"Ü"]; // 220 0DC
[ascii addObject:#"Ý"]; // 221 0DD
[ascii addObject:#"Þ"]; // 222 0DE
[ascii addObject:#"ß"]; // 223 0DF
// 0E0
[ascii addObject:#"à"]; // 224 0E0
[ascii addObject:#"á"]; // 225 0E1
[ascii addObject:#"â"]; // 226 0E2
[ascii addObject:#"ã"]; // 227 0E3
[ascii addObject:#"ä"]; // 228 0E4
[ascii addObject:#"å"]; // 229 0E5
[ascii addObject:#"æ"]; // 230 0E6
[ascii addObject:#"ç"]; // 231 0E7
[ascii addObject:#"è"]; // 232 0E8
[ascii addObject:#"é"]; // 233 0E9
[ascii addObject:#"ê"]; // 234 0EA
[ascii addObject:#"ë"]; // 235 0EB
[ascii addObject:#"ì"]; // 236 0EC
[ascii addObject:#"í"]; // 237 0ED
[ascii addObject:#"î"]; // 238 0EE
[ascii addObject:#"ï"]; // 239 0EF
// 0F0
[ascii addObject:#"ð"]; // 240 0F0
[ascii addObject:#"ñ"]; // 241 0F1
[ascii addObject:#"ò"]; // 242 0F2
[ascii addObject:#"ó"]; // 243 0F3
[ascii addObject:#"ô"]; // 244 0F4
[ascii addObject:#"õ"]; // 245 0F5
[ascii addObject:#"ö"]; // 246 0F6
[ascii addObject:#"÷"]; // 247 0F7
[ascii addObject:#"ø"]; // 248 0F8
[ascii addObject:#"ù"]; // 249 0F9
[ascii addObject:#"ú"]; // 250 0FA
[ascii addObject:#"û"]; // 251 0FB
[ascii addObject:#"ü"]; // 252 0FC
[ascii addObject:#"ý"]; // 253 0FD
[ascii addObject:#"þ"]; // 254 0FE
[ascii addObject:#"ÿ"]; // 255 0FF
NSInteger i;
for (i=0; i < self.length; i++) {
NSRange range;
range.location = i;
range.length = 1;
NSString *charString = [self substringWithRange:range];
for (NSInteger asciiIdx=0; asciiIdx < ascii.count; asciiIdx++) {
if ([charString isEqualToString:ascii[asciiIdx]]) {
unsigned char c = (unsigned char)asciiIdx;
output[i] = c;
break;
}
}
}
// Don't forget string termination
output[i] = 0;
return (const char*)&output[0];
}
#end

This is what I did using Swift 5:
func formatPassword() -> String {
var output = "";
for ch in self {
let char = String(ch)
switch ch {
case " ":
output.append("+")
break
case ".", "-", "_", "~", "a"..."z", "A"..."Z", "0"..."9":
output.append(char)
break
default:
print(ch)
let unicode = char.unicodeScalars.first?.value ?? 0
let unicodeValue = NSNumber(value: unicode).intValue
let hexValue = String(format: "%02X", arguments: [unicodeValue])
output = output.appendingFormat("%%%#", hexValue)
}
}
return output as String
}
Then I called this function where I defined my password.

Related

backtrace miss the function that caused a crash

I use backtrace and backtrace_symbols to collect the call stack when my app crashed.
void InstallSignalHandler(void)
{
signal(SIGHUP, SignalExceptionHandler);
signal(SIGINT, SignalExceptionHandler);
signal(SIGQUIT, SignalExceptionHandler);
signal(SIGABRT, SignalExceptionHandler);
signal(SIGILL, SignalExceptionHandler);
signal(SIGSEGV, SignalExceptionHandler);
signal(SIGFPE, SignalExceptionHandler);
signal(SIGBUS, SignalExceptionHandler);
signal(SIGPIPE, SignalExceptionHandler);
}
void SignalExceptionHandler(int signal)
{
NSMutableString *mstr = [[NSMutableString alloc] init];
[mstr appendString:#"Stack:\n"];
void* callstack[128];
int i, frames = backtrace(callstack, 128);
char** strs = backtrace_symbols(callstack, frames);
for (i = 0; i <frames; ++i) {
[mstr appendFormat:#"%s\n", strs[i]];
}
NSLog(#"%#", mstr);
free(strs);
}
When I check the log in console, I just find the log miss the function that caused the crash.The function is:
+ (void)testCrash
{
int *nullPointer = NULL;
*nullPointer = 2019;
}
And the log in console is:
0 TestApp 0x0000000101d1e040 SignalExceptionHandler + 160
1 libsystem_platform.dylib 0x000000011002bb5d _sigtramp + 29
2 ??? 0x0000000000000000 0x0 + 0
3 TestApp 0x00000001019bbc6f __39+[MyCrashTesting showInViewController:]_block_invoke + 303
4 UIKit 0x000000010b09a559 -[UIAlertController _invokeHandlersForAction:] + 105
5 UIKit 0x000000010b09af5e __103-[UIAlertController _dismissAnimated:triggeringAction:triggeredByPopoverDimmingView:dismissCompletion:]_block_invoke.461 + 16
6 UIKit 0x000000010ae42ca2 -[UIPresentationController transitionDidFinish:] + 1346
7 UIKit 0x000000010ae46b12 __56-[UIPresentationController runTransitionForCurrentState]_block_invoke.436 + 183
8 UIKit 0x000000010ba2a3b4 -[_UIViewControllerTransitionContext c
I have thought the function name "testCrash" should be in the top of the log. Does I do something wrong?
Since this is a very simple method with no arguments and no ARC heavylifting inside clang the Objective-C compiler is able to do an optimization (-O1 is enough to achieve that) of removing the message runtime call.
You can prevent this behavior with:
+ (void)testCrash __attribute__((optnone))
{
int *nullPointer = NULL;
*nullPointer = 2019;
}
The lesson learnt here is you should never rely on particular stacktrace to achieve something during your program execution. Diagnostics is fine as long as you understand the optimizing principles you've just encountered.

Getting IPV4 address as a String

Im using Bonjour to browse for available services from specific devices. I can successfully obtain and resolve the services returned from the browse, however I would like to take the service and retrieve it's IPV4 address in String form. To do this I am using the arpa/inet library to translate the NSdata object received by the NSNetService.addresses into a String. The code below works most of the time however occasionally the line below results in the crashing of the app.
NSString *ipString = [NSString stringWithFormat: #"%s",
inet_ntoa(socketAddress->sin_addr)];
The error: EXC_BAD_ACCESS
I am sure it has to do with the way I have declared this code, any ideas?
+ (NSString *)getStringFromAddressData:(NSData *)dataIn {
struct sockaddr_in *socketAddress = nil;
socketAddress = (struct sockaddr_in *)[dataIn bytes];
NSString *ipString = [NSString stringWithFormat: #"%s", inet_ntoa(socketAddress->sin_addr)];
return ipString;
}
Stack trace:
2015-08-13 08:23:45.860 Semiphores[4664:2119558] Stack trace : (
0 Semiphores 0x0000000100001c0b +[BonjourAddressHelper getStringFromAddressData:] + 107
1 Semiphores 0x0000000100007c8a _TFFC10Semiphores17BonjourController15resolveServicesFS0_FPSs9AnyObject_T_U_FT_T_ + 2682
2 Semiphores 0x0000000100007207 _TTRXFo__dT__XFdCb__dT__ + 39
3 libdispatch.dylib 0x00000001006852bb _dispatch_call_block_and_release + 12
4 libdispatch.dylib 0x000000010067fd43 _dispatch_client_callout + 8
5 libdispatch.dylib 0x0000000100683283 _dispatch_root_queue_drain + 1471
6 libdispatch.dylib 0x0000000100694cd0 _dispatch_worker_thread3 + 106
7 libsystem_pthread.dylib 0x00007fff86770637 _pthread_wqthread + 729
8 libsystem_pthread.dylib 0x00007fff8676e40d start_wqthread + 13
)
What would happen if someone passed in nil data?
+ (NSString *)getStringFromAddressData:(NSData *)dataIn {
if (dataIn != nil) {
struct sockaddr_in *socketAddress = nil;
socketAddress = (struct sockaddr_in *)[dataIn bytes];
NSString *ipString = [NSString stringWithFormat: #"%s", inet_ntoa(socketAddress->sin_addr)];
return ipString;
}
return #"";
}

Getting CocoaLibSpotify error in SPPlaylist.m

When I try to build my project i get the following error on line 827
/PATH_TO_PROJECT/Libs/CocoaLibSpotify/Model/SPPlaylist.m:827:25: Implicit conversion of Objective-C pointer type 'AVAssetTrack *' to C pointer type 'sp_track *' (aka 'struct sp_track *') requires a bridged cast
Here is the code where the error occurs:
805 -(void)addItems:(NSArray *)newItems atIndex:(NSUInteger)index callback:(SPErrorableOperationCallback)block {
806
807 SPDispatchAsync(^{
808
809 if (newItems.count == 0) {
810 dispatch_async(dispatch_get_main_queue(), ^{
811 if (block) block([NSError spotifyErrorWithCode:SP_ERROR_INVALID_INDATA]);
812 });
813 return;
814 }
815
816 sp_track **tracks = malloc(sizeof(sp_track *) * newItems.count);
817
818 // libSpotify iterates through the array and inserts each track at the given index,
819 // which ends up reversing the expected order. Defeat this by constructing a backwards
820 // array.
821 for (int currentTrack = (int)newItems.count - 1; currentTrack >= 0; currentTrack--) {
822
823 sp_track *track;
824 id item = [newItems objectAtIndex:currentTrack];
825
826 if ([item isKindOfClass:[SPTrack class]])
827 track = [item track];
828 else
829 track = [(SPTrack *)((SPPlaylistItem *)item).item track];
830
831 tracks[currentTrack] = track;
832 }
833 sp_track *const *trackPointer = tracks;
834
835 if (block)
836 [self.addCallbackStack addObject:block];
837
838 sp_error errorCode = sp_playlist_add_tracks(self.playlist, trackPointer, (int)newItems.count, (int)index, self.session.session);
839 free(tracks);
840 tracks = NULL;
841
842 NSError *error = nil;
843 if (errorCode != SP_ERROR_OK)
844 error = [NSError spotifyErrorWithCode:errorCode];
845
846 if (error && block) {
847 [self.addCallbackStack removeObject:block];
848 dispatch_async(dispatch_get_main_queue(), ^{ block(error); });
849 }
850 });
851 }
Thanks for your help!
The error is pretty self-explanatory - you need to make a bridged cast.
track = (__bridge sp_track *)[item track];
or
track = [(SPPlaylistItem *)item track];

why is code not executing on return from Future in Dart program

Could someone please explain to me why in the following code (using r25630 Windows), the value of iInsertTot at line 241 is null, or more to the point, why is line 234 ("return iInsertTot;") not executed and therefore at line 241, iInsertTot is null. The value of iInsertTot at lines 231/232 is an integer. While I can and probably should code this differently, I thought that I would try and see if it worked, because my understanding of Futures and Chaining was that it would work. I have used “return” in a similar way before and it worked, but I was returning null in those cases (eg. line 201 below).
/// The problem lines are :
233 fUpdateTotalsTable().then((_) {
234 return iInsertTot;
235 });
While running in the debugger, it appears that line 234 “return iInsertTot;” is never actually executed. Running from command line has the same result.
The method being called on line 233 (fUpdateTotalsTable) is something I am just in the process of adding, and it consists basically of sync code at this stage. However, the debugger appears to go through it correctly.
I have included the method “fUpdateTotalsTable()” (line 1076) just in case that is causing a problem.
Lines 236 to 245 have just been added, however just in case that code is invalid I have commented those lines out and run with the same problem occurring.
218 /*
219 * Process Inserts
220 */
221 }).then((_) {
222 sCheckpoint = "fProcessMainInserts";
223 ogPrintLine.fPrintForce ("Processing database ......");
224 int iMaxInserts = int.parse(lsInput[I_MAX_INSERTS]);
225 print ("");
226 return fProcessMainInserts(iMaxInserts, oStopwatch);
227 /*
228 * Update the 'totals' table with the value of Inserts
229 */
230 }).then((int iReturnVal) {
231 int iInsertTot = iReturnVal;
232 sCheckpoint = "fUpdateTotalsTable (insert value)";
233 fUpdateTotalsTable().then((_) {
234 return iInsertTot;
235 });
236 /*
237 * Display totals for inserts
238 */
239 }).then((int iInsertTot) {
240 ogTotals.fPrintTotals(
241 "${iInsertTot} rows inserted - Inserts completed",
242 iInsertTot, oStopwatch.elapsedMilliseconds);
243
244 return null;
245 /*
192 /*
193 * Clear main table if selected
194 */
195 }).then((tReturnVal) {
196 if (tReturnVal)
197 ogPrintLine.fPrintForce("Random Keys Cleared");
198 sCheckpoint = "Clear Table ${S_TABLE_NAME}";
199 bool tClearTable = (lsInput[I_CLEAR_YN] == "y");
200 if (!tFirstInstance)
201 return null;
202 return fClearTable(tClearTable, S_TABLE_NAME);
203
204 /*
205 * Update control row to increment count of instances started
206 */
207 }).then((_) {
1073 /*
1074 * Update totals table with values from inserts and updates
1075 */
1076 async.Future<bool> fUpdateTotalsTable() {
1077 async.Completer<bool> oCompleter = new async.Completer<bool>();
1078
1079 String sCcyValue = ogCcy.fCcyIntToString(ogTotals.iTotAmt);
1080
1081 print ("\n********* Total = ${sCcyValue} \n");
1082
1083 oCompleter.complete(true);
1084 return oCompleter.future;
1085 }
Your function L230-235 does not return anything and that's why your iInsertTot is null L239. To make it work you have to add a return at line 233.
231 int iInsertTot = iReturnVal;
232 sCheckpoint = "fUpdateTotalsTable (insert value)";
233 return fUpdateTotalsTable().then((_) {
234 return iInsertTot;
235 });

Why my [UIScrollView removeFromSuperview] is crashing?

The crash log is below.
Do you know any particular reason why might [UIScrollView removeFromSuperview] can crash? The scrollview contains view hierarchy with different types of UIViews. I also finds that the ad hoc version crash often not the debug version. I could not find any reason for that.
Same viewcontroller is loaded in a different flow in iPhone that works fine. But in iPad it crashes.
In iPad, in a container view controller, only viewcontroler.view is loaded.
Incident Identifier: EE102239-34D1-4BE7-8B52-41F74AB26203
CrashReporter Key: 2b11ea2a01ac5618e199ffc5a1e1f321600bb6a9
Hardware Model: iPad3,4
Version: ??? (???)
Code Type: ARM (Native)
Parent Process: launchd [1]
Date/Time: 2013-06-18 15:19:16.132 +0200
OS Version: iOS 6.1.3 (10B329)
Report Version: 104
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x3bab7070 prepareForMethodLookup + 20
1 libobjc.A.dylib 0x3bab6fb2 lookUpMethod + 42
2 libobjc.A.dylib 0x3bab6f7e _class_lookupMethodAndLoadCache3 + 14
3 libobjc.A.dylib 0x3bab6638 objc_msgSend_uncached + 24
4 QuartzCore 0x357f2a72 CA::Layer::contents_visibility_changed(CA::Transaction*, bool) + 50
5 QuartzCore 0x357f29de CA::Layer::mark_visible(CA::Transaction*, bool) + 190
6 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
7 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
8 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
9 QuartzCore 0x357f29b2 CA::Layer::mark_visible(CA::Transaction*, bool) + 146
10 QuartzCore 0x357f28d2 CA::Layer::update_removed_sublayer(CA::Transaction*, unsigned int) + 18
11 QuartzCore 0x357f255a CA::Layer::remove_sublayer(CA::Transaction*, CALayer*) + 130
12 QuartzCore 0x357f246a CA::Layer::remove_from_superlayer() + 34
13 UIKit 0x35a6e92c -[UIView(Hierarchy) removeFromSuperview] + 144
14 UIKit 0x35b857bc -[UIScrollView removeFromSuperview] + 60
15 MyApp 0x000bde8a -[iPadNavigationController vcAnimationDone] (iPadNavigationController.m:400)
16 UIKit 0x35a55ab6 -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] + 154
17 UIKit 0x35aca8f8 -[UIViewAnimationState animationDidStop:finished:] + 44
18 QuartzCore 0x35801304 CA::Layer::run_animation_callbacks(void*) + 204
19 libdispatch.dylib 0x3bed55d8 _dispatch_client_callout + 20
20 libdispatch.dylib 0x3bed8e40 _dispatch_main_queue_callback_4CF + 224
21 CoreFoundation 0x33c051ac __CFRunLoopRun + 1284
22 CoreFoundation 0x33b78238 CFRunLoopRunSpecific + 352
23 CoreFoundation 0x33b780c4 CFRunLoopRunInMode + 100
24 GraphicsServices 0x37733336 GSEventRunModal + 70
25 UIKit 0x35a942b4 UIApplicationMain + 1116
A few line from the code (as asked),
previous = showing;
showing = [ vc retain ];
showing.view.frame = startFrameIn;
[ container addSubview:showing.view ];
CGContextRef context = UIGraphicsGetCurrentContext();
[ UIView beginAnimations:nil context:context ];
[ UIView setAnimationDelegate:self ];
[ UIView setAnimationDidStopSelector:#selector(vcAnimationDone) ];
[ UIView setAnimationCurve:UIViewAnimationCurveEaseOut ];
[ UIView setAnimationDuration:0.4 ];
previous.view.frame = endFrameOut;
showing.view.frame = detailFrame;
[ UIView commitAnimations ];
}
- (void) vcAnimationDone {
if ( previous != nil ) {
if (previous.view.superview != nil) {
[previous.view removeFromSuperview];
}
[ previous release ];
previous = nil;
}
A very probable reason is that you are overreleasing your scrollview or one of the views inside it.
Calling removeFromSuperview then deallocates the view instead of simply decreasing the retain count.
Actually, if you are still stuck with non-ARC project, Static Code Analysis is very useful for this kind of bug. Retain/release balancing issues are hard to pin down, and nearly impossible with incomplete method so I suggest you post the full method body if possible.
Thanks everyone for your answers, tips and tricks. However one thing I want share with you is the cause of the crash. I found that the crash was at different thread in different times. I had several views loaded with button pressing/menu in my iPad app. Some of the button pressing fetch data from web service. So I was bit confused to get the cuase of crash, animation, or url connection etc... I tried with enabled NSZombie objects, but it did not show any information.
Then I tried with Guard Malloc. This only runs in Simulator. And magically I found the code point of crash. I have function to convert a hex string into data. There I have line of code to make a C string null terminated. where I assigned 0 at the last index. and that makes the crash!
tmpCh[count] = 0;
I do not why, but probably it takes some time in the memory management procedure in iOS so it crash at different thread at different times. But with Guard malloc in Simulator, it always point out here and when I rewrite the code, the crash is gone.
/* Converts a hex string to bytes.
Precondition:
. The hex string can be separated by space or not.
. the string length without space or 0x, must be even. 2 symbols for one byte/char
. sample input: 23 3A F1 OR 233AF1
*/
+ (NSData *) dataFromHexString:(NSString*)hexString
{
if (hexString.length < 1) {
return nil;
}
char * tmpCh = (char *) malloc([hexString length] * sizeof(char));
int count = 0;
for (int k=0; k<hexString.length;k++) {
char c = [hexString characterAtIndex:k];
if (c == (char)0x20) { //skip space
continue;
}
if (c == '0') { // skip 0x
if(k+1 < hexString.length){
if ([hexString characterAtIndex:k+1] == 'x'
|| [hexString characterAtIndex:k+1] == 'X' )
{
k = k + 1;
continue;
}
}
}
tmpCh[count] = c;
count++;
}
tmpCh[count] = 0; // make null terminated string
if (count % 2) {
return nil;
}
NSString *temp = [[NSString alloc] initWithUTF8String:tmpCh];
free(tmpCh);
if ([temp length] % 2 != 0) {
return nil;
}
NSMutableData *result = [[NSMutableData alloc] init];
unsigned char byte;
char hexChars[3] = {0};
for (int i=0; i < (temp.length/2); i++) {
hexChars[0] = [temp characterAtIndex:i*2];
hexChars[1] = [temp characterAtIndex:i*2+1];
if (![Util isValidChar:hexChars[0]] || ![Util isValidChar:hexChars[1]]) {
return nil;
}
byte = strtol(hexChars, NULL, 16);
[result appendBytes:&byte length:1];
}
NSData * data = [NSData dataWithData:result];
[result release];
return data;
}

Resources