การแทนที่ stringByAddingPercentEscapesUsingEncoding ใน ios9?


112

ใน iOS8 และก่อนหน้านี้ฉันสามารถใช้:

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

ใน iOS9 stringByAddingPercentEscapesUsingEncodingถูกแทนที่ด้วยstringByAddingPercentEncodingWithAllowedCharacters:

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

และคำถามของฉันคือจะหาสิ่งที่จำเป็นNSCharacterSet( NSUTF8StringEncoding) สำหรับการเปลี่ยนที่เหมาะสมได้stringByAddingPercentEscapesUsingEncodingที่ไหน

คำตอบ:


131

ข้อความเลิกใช้งานกล่าวว่า (เน้นของฉัน):

ใช้ stringByAddingPercentEncodingWithAllowedCharacters (_ :) แทนซึ่งจะใช้การเข้ารหัส UTF-8 ที่แนะนำเสมอและการเข้ารหัสใดสำหรับส่วนประกอบ URL หรือส่วนประกอบย่อยที่เฉพาะเจาะจงเนื่องจากคอมโพเนนต์ URL หรือส่วนประกอบย่อยแต่ละรายการมีกฎที่แตกต่างกันสำหรับอักขระที่ใช้ได้

ดังนั้นคุณต้องจัดหาNSCharacterSetอาร์กิวเมนต์ให้เพียงพอเท่านั้น โชคดีสำหรับ URL มีวิธีการคลาสที่สะดวกมากซึ่งเรียกURLHostAllowedCharacterSetว่าคุณสามารถใช้ได้ดังนี้:

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

อัปเดตสำหรับSwift 3 - วิธีนี้กลายเป็นคุณสมบัติคงที่urlHostAllowed:

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

โปรดทราบว่า:

วิธีนี้มีจุดมุ่งหมายเพื่อเข้ารหัสเปอร์เซ็นต์ส่วนประกอบ URL หรือสตริงส่วนประกอบย่อยไม่ใช่สตริง URL ทั้งหมด


6
นอกจากนี้ฉันขอแนะนำอย่างยิ่งให้ใช้NSURLComponentsซึ่งสามารถจัดการการเข้ารหัสเปอร์เซ็นต์ให้คุณได้
Antonio Favata

1
มีข้อเสนอแนะเกี่ยวกับสิ่งที่ต้องใช้สำหรับสตริง URL ทั้งหมดหรือไม่
ทักษะ M2

1
@ SkillM2 ฉันคิดว่าNSURLComponents(ด้วยการเข้ารหัสเปอร์เซ็นต์ส่วนประกอบแต่ละส่วนที่เกี่ยวข้องNSCharacterSet) เป็นวิธีที่ถูกต้อง
Antonio Favata

2
คุณไม่ควรเคยไม่พยายามเข้ารหัสสตริง URL ทั้งหมด อาจทำให้เกิดข้อบกพร่องที่ไม่คาดคิดและในบางกรณีช่องโหว่ด้านความปลอดภัย วิธีเดียวที่รับประกันว่าจะเข้ารหัส URL ได้อย่างถูกต้องคือทำทีละชิ้น
dgatwood

ยิ่งใหญ่ ขอบคุณมากเพื่อน!
Felipe

100

สำหรับ Objective-C:

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

จะหา set สำหรับ NSUTF8StringEncoding ได้ที่ไหน

มีชุดอักขระที่กำหนดไว้ล่วงหน้าสำหรับส่วนประกอบ URL หกรายการและส่วนประกอบย่อยซึ่งอนุญาตให้มีการเข้ารหัสเปอร์เซ็นต์ -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

ข้อความเลิกใช้งานกล่าวว่า (เน้นของฉัน):

ใช้ stringByAddingPercentEncodingWithAllowedCharacters (_ :) แทนซึ่งจะใช้การเข้ารหัส UTF-8 ที่แนะนำเสมอและการเข้ารหัสใดสำหรับส่วนประกอบ URL หรือส่วนประกอบย่อยที่เฉพาะเจาะจงเนื่องจากคอมโพเนนต์ URL หรือส่วนประกอบย่อยแต่ละรายการมีกฎที่แตกต่างกันสำหรับอักขระที่ใช้ได้

ดังนั้นคุณต้องจัดหาNSCharacterSetอาร์กิวเมนต์ให้เพียงพอเท่านั้น โชคดีสำหรับ URL มีวิธีการคลาสที่สะดวกมากซึ่งเรียกURLHostAllowedCharacterSetว่าคุณสามารถใช้ได้ดังนี้:

NSCharacterSet *set = [NSCharacterSet URLHostAllowedCharacterSet]; 

โปรดทราบว่า:

วิธีนี้มีจุดมุ่งหมายเพื่อเข้ารหัสเปอร์เซ็นต์ส่วนประกอบ URL หรือสตริงส่วนประกอบย่อยไม่ใช่สตริง URL ทั้งหมด


4
ฉันชอบตอนที่ Apple ทำให้ชีวิตง่ายขึ้น ขอบคุณแอปเปิ้ล
เป็ด

5
ความหมายของ "วิธีนี้มีไว้เพื่อเข้ารหัสเปอร์เซ็นต์ส่วนประกอบ URL หรือสตริงส่วนประกอบย่อยไม่ใช่สตริง URL ทั้งหมด" ?
GeneCode

4
URLHostAllowedCharacterSet แสดงข้อผิดพลาด "Unsupported URL" ฉันใช้ URLFragmentAllowedCharacterSet และทำงานได้ดี
anoop4real

1
สิ่งนี้ใช้ไม่ได้กับ + จะไม่เข้ารหัสและจะถูกแทนที่ด้วยช่องว่างบนฝั่งเซิร์ฟเวอร์ตามข้อกำหนด
Torge

45

URLHostAllowedCharacterSetจะไม่ทำงานสำหรับฉัน ฉันใช้URLFragmentAllowedCharacterSetแทน

วัตถุประสงค์ -C

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

SWIFT - 4

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

ต่อไปนี้เป็นชุดอักขระที่มีประโยชน์ (กลับหัว):

URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}
URLHostAllowedCharacterSet      "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet     "#%<>[\]^`{|}
URLUserAllowedCharacterSet      "#%/:<>?@[\]^`

ขอขอบคุณและเช่นเดียวกันกับคุณ
Arpit B Parekh

น่าสังเกตว่าไม่มีชุดเหล่านี้รวม+อยู่ด้วย ดังนั้นเครื่องหมายบวกในสตริงจะยุ่งเหยิงหากส่งผ่านในพารามิเตอร์การค้นหา - ถือว่าเป็นช่องว่าง `` ทางฝั่งเซิร์ฟเวอร์
Asmo Soinio

21

Objective-C

รหัสนี้ใช้ได้กับฉัน:

urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];

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;
}
}

2

สำหรับ Swift 3.0

คุณสามารถใช้urlHostAllowedcharacterSet

/// ส่งคืนชุดอักขระสำหรับอักขระที่อนุญาตในองค์ประกอบย่อยของโฮสต์ URL

public static var urlHostAllowed: CharacterSet { get }

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

1

ความหมายของ "วิธีนี้มีไว้เพื่อเข้ารหัสเปอร์เซ็นต์ของส่วนประกอบ URL หรือสตริงส่วนประกอบย่อยไม่ใช่สตริง URL ทั้งหมด" ? - GeneCode 1 ก.ย. 59 เวลา 08:30 น

หมายความว่าคุณไม่ควรเข้ารหัสhttps://xpto.example.com/path/subpathurl แต่จะเกิดขึ้นหลังจากไฟล์?.

สมมติว่าเนื่องจากมีการใช้งานในกรณีเช่น:

https://example.com?redirectme=xxxxx

xxxxxURL ที่เข้ารหัสแบบเต็มอยู่ที่ไหน


0

การเพิ่มคำตอบที่ยอมรับ คำนึงถึงบันทึกนี้

วิธีนี้มีจุดมุ่งหมายเพื่อเข้ารหัสเปอร์เซ็นต์ส่วนประกอบ URL หรือสตริงส่วนประกอบย่อยไม่ใช่สตริง URL ทั้งหมด

ไม่ควรเข้ารหัส URL ทั้งหมด:

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!
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.