Zamiennik dla stringByAddingPercentEscapesUsingEncoding w ios9?

112

W iOS8 i wcześniejszych mogę używać:

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

w iOS9 stringByAddingPercentEscapesUsingEncodingzostał zastąpiony przez stringByAddingPercentEncodingWithAllowedCharacters:

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

a moje pytanie brzmi: gdzie znaleźć potrzebne NSCharacterSet( NSUTF8StringEncoding) do poprawnej wymiany stringByAddingPercentEscapesUsingEncoding?

slavik
źródło

Odpowiedzi:

131

Komunikat o wycofaniu mówi (moje podkreślenie):

Zamiast tego użyj stringByAddingPercentEncodingWithAllowedCharacters (_ :), które zawsze używa zalecanego kodowania UTF-8 i które koduje dla określonego składnika lub podskładnika adresu URL, ponieważ każdy składnik lub podskładnik adresu URL ma inne zasady dotyczące prawidłowych znaków.

Musisz więc podać tylko odpowiedni NSCharacterSetargument. Na szczęście w przypadku adresów URL istnieje bardzo przydatna metoda klasowa URLHostAllowedCharacterSet, której można użyć w następujący sposób:

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

Aktualizacja dla Swift 3 - metoda staje się właściwością statyczną urlHostAllowed:

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

Pamiętaj jednak, że:

Ta metoda jest przeznaczona do kodowania procentowego składnika adresu URL lub ciągu podskładnika, a NIE całego ciągu adresu URL.

Antonio Favata
źródło
6
Ponadto zdecydowanie sugerowałbym użycie NSURLComponents, które może obsługiwać kodowanie procentowe za Ciebie.
Antonio Favata
1
Jakieś sugestie, czego użyć dla całego ciągu adresu URL?
Skill M2
1
@ SkillM2 Myślę, że NSURLComponents(z każdym komponentem zakodowanym procentowo z odpowiednim NSCharacterSet) jest właściwą drogą.
Antonio Favata
2
Nigdy, przenigdy nie powinieneś próbować zakodować całego ciągu adresu URL. Może powodować nieoczekiwane błędy, aw niektórych przypadkach luki w zabezpieczeniach. Jedynym gwarantowanym poprawnym sposobem zakodowania adresu URL jest zrobienie tego po jednym fragmencie na raz.
dgatwood
Wspaniały. Wielkie dzięki, stary!
Felipe
100

Dla celu C :

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

gdzie znaleźć zestaw dla NSUTF8StringEncoding?

Istnieją predefiniowane zestawy znaków dla sześciu składników adresu URL i podskładników, które umożliwiają kodowanie procentowe. Te zestawy znaków są przekazywane do -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

Komunikat o wycofaniu mówi (moje podkreślenie):

Zamiast tego użyj stringByAddingPercentEncodingWithAllowedCharacters (_ :), które zawsze używa zalecanego kodowania UTF-8 i które koduje dla określonego składnika lub podskładnika adresu URL, ponieważ każdy składnik lub podskładnik adresu URL ma inne zasady dotyczące prawidłowych znaków.

Musisz więc podać tylko odpowiedni NSCharacterSetargument. Na szczęście w przypadku adresów URL istnieje bardzo przydatna metoda klasowa URLHostAllowedCharacterSet, której można użyć w następujący sposób:

NSCharacterSet *set = [NSCharacterSet URLHostAllowedCharacterSet]; 

Pamiętaj jednak, że:

Ta metoda jest przeznaczona do kodowania procentowego składnika adresu URL lub ciągu podskładnika, a NIE całego ciągu adresu URL.

ElonChan
źródło
4
Uwielbiam, gdy Apple ułatwia życie. Dzięki jabłku.
Duck
5
Co oznacza „Ta metoda jest przeznaczona do kodowania procentowego składnika adresu URL lub ciągu podskładnika, a NIE całego ciągu adresu URL”. ?
GeneCode
4
URLHostAllowedCharacterSet wyświetlał błąd „Nieobsługiwany adres URL”, użyłem zestawu URLFragmentAllowedCharacterSet i działa poprawnie.
anoop4real
1
to nie działa z +, nie zakoduje go i zostanie zastąpione spacją po stronie serwera zgodnie ze specyfikacją.
Torge
45

URLHostAllowedCharacterSetjest NIE PRACA DLA MNIE. Używam URLFragmentAllowedCharacterSetzamiast tego.

CEL C

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

SWIFT - 4

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

Oto przydatne (odwrócone) zestawy znaków:

URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}
URLHostAllowedCharacterSet      "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet     "#%<>[\]^`{|}
URLUserAllowedCharacterSet      "#%/:<>?@[\]^`
Lal Krishna
źródło
Dziękuję i tobie również
Arpit B Parekh
Warto zauważyć, że żaden z tych zestawów nie zawiera +. Tak więc znaki plus w ciągu zostaną pomieszane, jeśli zostaną przekazane w parametrach zapytania - traktowane jako spacja `` po stronie serwera.
Asmo Soinio
21

Cel C

ten kod działa dla mnie:

urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
Bilal L
źródło
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
źródło
2

Dla Swift 3.0

Możesz użyć urlHostAllowedzestawu znaków.

/// Zwraca zestaw znaków dla znaków dozwolonych w podskładniku adresu URL hosta.

public static var urlHostAllowed: CharacterSet { get }

WebserviceCalls.getParamValueStringForURLFromDictionary(settingsDict as! Dictionary<String, AnyObject>).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed)
technerd
źródło
1

Co oznacza „Ta metoda jest przeznaczona do kodowania procentowego składnika adresu URL lub ciągu podskładnika, a NIE całego ciągu adresu URL”. ? - GeneCode 1 września 2016 o 8:30

Oznacza to, że nie powinieneś kodować adresu https://xpto.example.com/path/subpathURL, a tylko to, co następuje po ?.

Przypuszczalnie, ponieważ istnieją przypadki użycia do zrobienia tego w przypadkach takich jak:

https://example.com?redirectme=xxxxx

Gdzie xxxxxjest w pełni zakodowany adres URL.

kindaian
źródło
0

Dodawanie do zaakceptowanej odpowiedzi. Biorąc pod uwagę tę uwagę

Ta metoda jest przeznaczona do kodowania procentowego składnika adresu URL lub ciągu podskładnika, a NIE całego ciągu adresu URL.

cały adres URL nie powinien być kodowany:

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
źródło