Jawaban:
Sayangnya, stringByAddingPercentEscapesUsingEncoding
tidak selalu berhasil 100%. Ini mengkodekan karakter non-URL tetapi meninggalkan karakter yang dipesan (seperti slash /
dan ampersand &
) sendirian. Rupanya ini adalah bug yang diketahui Apple, tetapi karena mereka belum memperbaikinya, saya telah menggunakan kategori ini untuk meng-url-encode sebuah 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;
}
Digunakan seperti ini:
NSString *urlEncodedString = [@"SOME_URL_GOES_HERE" urlencode];
// Or, with an already existing string:
NSString *someUrlString = @"someURL";
NSString *encodedUrlStr = [someUrlString urlencode];
Ini juga berfungsi:
NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8 );
Beberapa bacaan yang bagus tentang subjek:
Objektif-c iPhone persen menyandikan string?
Pengodean Objective-C dan Swift URL
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 /
Ini mungkin bermanfaat
NSString *sampleUrl = @"http://www.google.com/search.jsp?params=Java Developer";
NSString* encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding];
Untuk iOS 7+, cara yang disarankan adalah:
NSString* encodedUrl = [sampleUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
Anda dapat memilih set karakter yang diizinkan sesuai persyaratan komponen URL.
-stringByAddingPercentEncodingWithAllowedCharacters:
Sebagai gantinya, gunakan yang selalu menggunakan pengkodean UTF-8 yang direkomendasikan, dan yang mengkodekan untuk komponen URL tertentu atau subkomponen karena setiap komponen URL atau subkomponen memiliki aturan yang berbeda untuk karakter apa yang valid."
API baru telah ditambahkan sejak jawaban dipilih; Anda sekarang dapat menggunakan NSURLUtilities. Karena berbagai bagian URL memungkinkan karakter yang berbeda, gunakan rangkaian karakter yang berlaku. Contoh berikut ini dikodekan untuk dimasukkan dalam string kueri:
encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
Untuk secara khusus mengonversi '&', Anda harus menghapusnya dari set kueri url atau menggunakan set lain, karena '&' diizinkan dalam kueri URL:
NSMutableCharacterSet *chars = NSCharacterSet.URLQueryAllowedCharacterSet.mutableCopy;
[chars removeCharactersInRange:NSMakeRange('&', 1)]; // %26
encodedString = [myString stringByAddingPercentEncodingWithAllowedCharacters:chars];
NSMakeRange('&', 1)
tidak berfungsi di Swift, karena Swift tidak mengizinkan konversi char ke int tanpa peretasan. Untuk menggunakan solusi ini dalam kode Swift, gunakan removeCharactersInString("&")
sebagai ganti.removeCharactersInRange(...)
Contoh Swift 2.0 (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
}
}
pembaruan ios 7
NSString *encode = [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *decode = [encode stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
Saya memilih untuk menggunakan CFURLCreateStringByAddingPercentEscapes
panggilan seperti yang diberikan oleh jawaban yang diterima, namun dalam versi terbaru XCode (dan iOS), itu menghasilkan kesalahan, jadi gunakan yang berikut sebagai gantinya:
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));
Cobalah menggunakan stringByAddingPercentEncodingWithAllowedCharacters
metode dengan [NSCharacterSet URLUserAllowedCharacterSet]
itu akan mencakup semua kasus
Tujuan C
NSString *value = @"Test / Test";
value = [value stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLUserAllowedCharacterSet]];
cepat
var value = "Test / Test"
value.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLUserAllowedCharacterSet())
Keluaran
Test%20%2F%20Test
Setelah membaca semua jawaban untuk topik ini dan yang ( salah ) diterima, saya ingin menambahkan kontribusi saya.
JIKA targetnya adalah iOS7 +, dan pada 2017 semestinya sejak XCode membuat sangat sulit untuk memberikan kompatibilitas di bawah iOS8, cara terbaik, aman thread, cepat, dan akan dukungan penuh UTF-8 untuk melakukan ini adalah:
(Kode C tujuan)
@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
Ini akan memperluas NSString, akan mengecualikan karakter terlarang RFC, mendukung karakter UTF-8, dan membiarkan Anda menggunakan hal-hal seperti:
NSString *myusername = "I'm[evil]&want(to)break!!!$->àéìòù";
NSLog(@"Source: %@ -> Dest: %@", myusername, [myusername urlencode]);
Itu akan dicetak pada konsol debug Anda:
Sumber: Saya [jahat] & ingin istirahat !!! $ -> àéìòù -> Dest: I% 27m% 5Bevil% 5D% 26ingin% 28ke% 29break% 21% 21% 21% 24-% 3E% C3 % A0% C3% A9% C3% AC% C3% B2% C3% B9
... perhatikan juga penggunaan dispatch_once untuk menghindari beberapa inisialisasi dalam lingkungan multithread.
Berikut ini adalah pendekatan fleksibel siap-produksi di 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())
}
}
print("Hello, World!".urlEncoded()!)
print("You&Me?".urlEncoded()!)
print("#Blessed 100%".urlEncoded()!)
print("Pride and Prejudice".urlEncoded(denying: .uppercaseLetters)!)
Hello,%20World!
You%26Me%3F
%23Blessed%20100%25
%50ride and %50rejudice
Gunakan komponen NSURLC untuk mengkodekan parameter GET HTTP:
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/
Kode ini membantu saya untuk penyandian karakter khusus
NSString* encPassword = [password stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]];
kode cepat berdasarkan jawaban objek chown di utas ini.
extension String {
func urlEncode() -> String {
return CFURLCreateStringByAddingPercentEscapes(
nil,
self,
nil,
"!*'();:@&=+$,/?%#[]",
CFStringBuiltInEncodings.UTF8.rawValue
)
}
}
Di Swift 3 , silakan coba di bawah ini:
let stringURL = "YOUR URL TO BE ENCODE";
let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(encodedURLString)
Karena, stringByAddingPercentEscapesUsingEncoding
menyandikan karakter bukan URL tetapi meninggalkan karakter yang dipesan (seperti !*'();:@&=+$,/?%#[]
), Anda dapat menyandikan url seperti kode berikut:
let stringURL = "YOUR URL TO BE ENCODE";
let characterSetTobeAllowed = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted)
if let encodedURLString = stringURL.addingPercentEncoding(withAllowedCharacters: characterSetTobeAllowed) {
print(encodedURLString)
}
Saran Apple, dalam catatan rilis 10.11, adalah:
Jika Anda perlu meng-enkode seluruh string URL, Anda dapat menggunakan kode ini untuk menyandikan NSString yang dimaksudkan sebagai URL (dalam urlStringToEncode):
NSString *percentEncodedURLString =
[[NSURL URLWithDataRepresentation:[urlStringToEncode dataUsingEncoding:NSUTF8StringEncoding] relativeToURL:nil] relativeString];
Dalam kasus saya di mana komponen terakhir adalah huruf Arab yang saya lakukan berikut di 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;
}
}
pemakaian:
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)
);
}
menurut blog berikut
Begitu banyak jawaban tetapi tidak berhasil untuk saya, jadi saya mencoba yang berikut:
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...
}
Semoga itu bisa membantu seseorang. Terima kasih
Untuk parameter kueri yang di-encode formulir www, saya membuat kategori di NSString:
- (NSString*)WWWFormEncoded{
NSMutableCharacterSet *chars = NSCharacterSet.alphanumericCharacterSet.mutableCopy;
[chars addCharactersInString:@" "];
NSString* encodedString = [self stringByAddingPercentEncodingWithAllowedCharacters:chars];
encodedString = [encodedString stringByReplacingOccurrencesOfString:@" " withString:@"+"];
return encodedString;
}
// Ini tanpa ujian
NSMutableCharacterSet* set = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
[set addCharactersInString:@"-_.~"];
NSString *encode = [test stringByAddingPercentEncodingWithAllowedCharacters:set];
Saya menghadapi masalah serupa melewati string kompleks sebagai parameter POST. String saya dapat berisi karakter Asia, spasi, kutipan, dan segala macam karakter khusus. Solusi yang akhirnya saya temukan adalah mengubah string saya menjadi seri unicodes yang cocok, misalnya "Hu0040Hu0020Hu03f5 ...." menggunakan [NSString stringWithFormat: @ "Hu% 04x", [string characterAtIndex: i]] untuk mendapatkan Unicode dari masing-masing karakter dalam string asli. Hal yang sama dapat dilakukan di Jawa.
String ini dapat dengan aman diteruskan sebagai parameter POST.
Di sisi server (PHP), saya mengubah semua "H" menjadi "\" dan saya meneruskan string yang dihasilkan ke json_decode. Langkah terakhir adalah menghindari tanda kutip tunggal sebelum menyimpan string ke dalam MySQL.
Dengan cara ini saya dapat menyimpan string UTF8 di server saya.
Yang ini bekerja untuk saya.
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
}
Saya menemukan fungsi di atas dari tautan ini: http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/
Anda juga dapat menggunakan fungsi ini dengan ekstensi cepat. Tolong beri tahu saya jika ada masalah.