Pengganti stringByAddingPercentEscapesUsingEncoding di ios9?

112

Di iOS8 dan sebelumnya saya dapat menggunakan:

NSString *str = ...; // some URL
NSString *result = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

di iOS9 stringByAddingPercentEscapesUsingEncodingtelah diganti dengan stringByAddingPercentEncodingWithAllowedCharacters:

NSString *str = ...; // some URL
NSCharacterSet *set = ???; // where to find set for NSUTF8StringEncoding?
NSString *result = [str stringByAddingPercentEncodingWithAllowedCharacters:set];

dan pertanyaan saya adalah: di mana menemukan yang dibutuhkan NSCharacterSet( NSUTF8StringEncoding) untuk penggantian yang tepat stringByAddingPercentEscapesUsingEncoding?

Slavik
sumber

Jawaban:

131

Pesan penghentian mengatakan (penekanan milik saya):

Gunakan stringByAddingPercentEncodingWithAllowedCharacters (_ :) sebagai gantinya, yang selalu menggunakan pengkodean UTF-8 yang disarankan , dan yang menyandikan untuk komponen atau subkomponen URL tertentu karena setiap komponen atau subkomponen URL memiliki aturan berbeda untuk karakter yang valid.

Jadi Anda hanya perlu memberikan NSCharacterSetargumen yang memadai . Untungnya, untuk URL, ada metode kelas yang sangat berguna yang disebut URLHostAllowedCharacterSetyang dapat Anda gunakan seperti ini:

let encodedHost = unencodedHost.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())

Pembaruan untuk Swift 3 - metode menjadi properti statis urlHostAllowed:

let encodedHost = unencodedHost.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

Namun, ketahuilah bahwa:

Metode ini ditujukan untuk persen-encode komponen URL atau string subkomponen, BUKAN seluruh string URL.

Antonio Favata
sumber
6
Juga, saya sangat menyarankan penggunaan NSURLComponents, yang dapat menangani encoding persen untuk Anda.
Antonio Favata
1
Ada saran tentang apa yang harus digunakan untuk seluruh string URL?
Skill M2
1
@ SkillM2 Saya pikir NSURLComponents(dengan masing-masing komponen persen-dikodekan dengan yang sesuai NSCharacterSet) adalah cara yang tepat untuk pergi.
Antonio Favata
2
Anda tidak boleh, pernah, mencoba menyandikan seluruh string URL. Ini dapat menyebabkan bug yang tidak terduga, dan dalam beberapa kasus, lubang keamanan. Satu-satunya cara yang dijamin benar untuk menyandikan URL adalah melakukannya satu per satu.
dgatwood
Bagus. Terima kasih banyak, sobat!
Felipe
100

Untuk Objective-C :

NSString *str = ...; // some URL
NSCharacterSet *set = [NSCharacterSet URLHostAllowedCharacterSet]; 
NSString *result = [str stringByAddingPercentEncodingWithAllowedCharacters:set];

di mana menemukan set untuk NSUTF8StringEncoding?

Ada himpunan karakter yang telah ditentukan untuk enam komponen URL dan subkomponen yang memungkinkan encoding persen. Kumpulan karakter ini diteruskan ke -stringByAddingPercentEncodingWithAllowedCharacters:.

 // Predefined character sets for the six URL components and subcomponents which allow percent encoding. These character sets are passed to -stringByAddingPercentEncodingWithAllowedCharacters:.
@interface NSCharacterSet (NSURLUtilities)
+ (NSCharacterSet *)URLUserAllowedCharacterSet;
+ (NSCharacterSet *)URLPasswordAllowedCharacterSet;
+ (NSCharacterSet *)URLHostAllowedCharacterSet;
+ (NSCharacterSet *)URLPathAllowedCharacterSet;
+ (NSCharacterSet *)URLQueryAllowedCharacterSet;
+ (NSCharacterSet *)URLFragmentAllowedCharacterSet;
@end

Pesan penghentian mengatakan (penekanan milik saya):

Gunakan stringByAddingPercentEncodingWithAllowedCharacters (_ :) sebagai gantinya, yang selalu menggunakan pengkodean UTF-8 yang disarankan , dan yang menyandikan untuk komponen atau subkomponen URL tertentu karena setiap komponen atau subkomponen URL memiliki aturan berbeda untuk karakter yang valid.

Jadi Anda hanya perlu memberikan NSCharacterSetargumen yang memadai . Untungnya, untuk URL, ada metode kelas yang sangat berguna yang disebut URLHostAllowedCharacterSetyang dapat Anda gunakan seperti ini:

NSCharacterSet *set = [NSCharacterSet URLHostAllowedCharacterSet]; 

Namun, ketahuilah bahwa:

Metode ini ditujukan untuk persen-encode komponen URL atau string subkomponen, BUKAN seluruh string URL.

ElonChan
sumber
4
Saya suka saat Apple membuat hidup lebih mudah. Terima kasih apel.
Bebek
5
Apa arti dari "Metode ini ditujukan untuk persen-encode komponen URL atau string subkomponen, BUKAN seluruh string URL." ?
GeneCode
4
URLHostAllowedCharacterSet memberikan kesalahan "URL Tidak Didukung", saya menggunakan URLFragmentAllowedCharacterSet dan berfungsi dengan baik.
anoop4real
1
ini tidak bekerja dengan + itu tidak akan menyandikannya dan itu akan digantikan oleh ruang di sisi server sesuai spesifikasi.
Torge
45

URLHostAllowedCharacterSetadalah tidak bekerja UNTUK ME. Saya gunakan URLFragmentAllowedCharacterSetsebagai gantinya.

TUJUAN -C

NSCharacterSet *set = [NSCharacterSet URLFragmentAllowedCharacterSet];
NSString * encodedString = [@"url string" stringByAddingPercentEncodingWithAllowedCharacters:set];

SWIFT - 4

"url string".addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

Berikut ini adalah kumpulan karakter (terbalik) yang berguna:

URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}
URLHostAllowedCharacterSet      "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet     "#%<>[\]^`{|}
URLUserAllowedCharacterSet      "#%/:<>?@[\]^`
Lal Krishna
sumber
Terima kasih dan sama juga untuk Anda
Arpit B Parekh
Perlu diperhatikan bahwa tidak satu pun dari set ini termasuk +. Jadi tanda plus dalam string akan kacau jika diteruskan dalam parameter kueri - diperlakukan sebagai spasi `` di sisi server.
Asmo Soinio
21

Objective-C

kode ini bekerja untuk saya:

urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
Bilal L.
sumber
4

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;
}
}
Bobj-C
sumber
2

Untuk Swift 3.0

Anda dapat menggunakan urlHostAllowedcharacterSet.

/// Mengembalikan set karakter untuk karakter yang diperbolehkan dalam subkomponen URL host.

public static var urlHostAllowed: CharacterSet { get }

WebserviceCalls.getParamValueStringForURLFromDictionary(settingsDict as! Dictionary<String, AnyObject>).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed)
technerd
sumber
1

Apa arti dari "Metode ini dimaksudkan untuk mengenkode persen komponen URL atau string subkomponen, BUKAN seluruh string URL." ? - GeneCode 1 Sep '16 jam 8:30

Ini berarti bahwa Anda tidak seharusnya menyandikan https://xpto.example.com/path/subpathurl, tetapi hanya apa yang terjadi setelah ?.

Seharusnya, karena ada kasus penggunaan untuk melakukannya dalam kasus seperti:

https://example.com?redirectme=xxxxx

Di mana xxxxxada URL yang dikodekan sepenuhnya.

kindaian
sumber
0

Menambah jawaban yang diterima. Mempertimbangkan catatan ini

Metode ini ditujukan untuk persen-encode komponen URL atau string subkomponen, BUKAN seluruh string URL.

seluruh URL tidak boleh dikodekan:

let param = "=color:green|\(latitude),\(longitude)&\("zoom=13&size=\(width)x\(height)")&sensor=true&key=\(staticMapKey)".addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) 
let url = "https://maps.google.com/maps/api/staticmap?markers" + param!
Ayman Ibrahim
sumber