2011-04-06 59 views
5

我有一串ASCII字符(由[NSString stringWithFormat:@「%c」,someNumber]隨機創建),我想用該字符串作爲javascript方法的輸入。例如:Escape NSString for javascript input

[webView_ stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"my_javascript_method(\"%@\")", myASCIIString]]; 

我該如何逃避NSString?我試圖調查encodeURI和decodeURI,但還沒有找到任何解決方案。

+0

備案:'stringByEvaluatingJavaScriptFromString'爲Unicode正確;您不必轉義非ASCII字符。 – 2014-03-22 16:35:07

回答

5

通過ASCII,我推測你的意思是它是一個範圍在0x00到0x7F之間的字節。在此範圍內,根據http://www.json.org,您需要轉義的唯一字符是\,"以及控制字符:0x00-0x1F和0x7F。控制字符變得有點棘手,如果你正在做的簡單替代,所以我會去通過逐個字符逃避串,也許這樣的事情(在所有未測試):

const char *chars = [myASCIIString UTF8String]; 
NSMutableString *escapedString = [NSMutableString string]; 
while (*chars) 
{ 
    if (*chars == '\\') 
     [escapedString appendString:@"\\\\"]; 
    else if (*chars == '"') 
     [escapedString appendString:@"\\\""]; 
    else if (*chars < 0x1F || *chars == 0x7F) 
     [escapedString appendFormat:@"\\u%04X", (int)*chars]; 
    else 
     [escapedString appendFormat:@"%c", *chars]; 
    ++chars; 
} 
NSString *js = [NSString stringWithFormat:@"my_js_function(\"%@\")", escapedString]; 
+0

該解決方案有效,但它有兩個錯誤。首先,這不會正確地轉義雙引號。它應該讀取'「\\\」「'而不是'」\「」'。其次,它會將轉義字符串追加到原始字符串中,而不是創建一個新字符串。第二行應該是這樣的:'NSMutableString * escapedString = [NSMutableString stringWithString:@「」];'。 – 2014-01-16 15:18:56

+0

@Eric:你是對的。我已經解決了答案。謝謝! – 2014-01-16 18:56:58

+0

轉義非ASCII碼不是必需的。至少從iOS 5開始,UIWebView就會使用非ASCII字面值。反正你做得不對;它會打破真正的高端Unicode字符。 – 2014-03-22 16:38:34

0

您是否嘗試過類似的事情:

[webView_ stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"my_javascript_method(escape(\"%@\"))", myASCIIString]]; 

只是刪除逃生功能到字符串調用可以爲你工作。這真的取決於你爲什麼要這樣逃脫

+0

我剛試過,它沒有工作,該方法沒有被調用。 我希望它逃脫的原因只是因爲我的ASCII字符串包含一些不可讀的字符(因爲它是從0-255的隨機數字的ASCII創建的),並且它打破了輸入。 – 2011-04-06 16:44:01

+0

這根本不會工作 – AlBeebe 2012-03-28 22:03:14

1

Here's the relevant part of the ES5 specification

所有的字符可以在字符串中除右引號字符,反斜槓,回車,換行分隔符,段落分隔符,和換行文字字面上出現。任何字符都可能以轉義序列的形式出現。

有反斜槓的某些字符(你可以找到幾個頁面向下),以及任何字符可以在十六進制表示爲\uXXXX。他們在規範中解釋了(有例子)幾頁。

9

無數個小時後在這裏研究解決方案就是我想到的。事實證明,我遇到了一個問題,我沒有逃避回車\ r所以這個功能解決了我的問題。

-(NSString *)addBackslashes:(NSString *)string { 
    /* 

    Escape characters so we can pass a string via stringByEvaluatingJavaScriptFromString 

    */ 

    // Escape the characters 
    string = [string stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; 
    string = [string stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; 
    string = [string stringByReplacingOccurrencesOfString:@"\'" withString:@"\\\'"]; 
    string = [string stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"]; 
    string = [string stringByReplacingOccurrencesOfString:@"\r" withString:@"\\r"]; 
    string = [string stringByReplacingOccurrencesOfString:@"\f" withString:@"\\f"]; 
    return string; 
} 

這是一個很棒的網站,我發現,讓我找到這個解決方案。 http://www.wilsonmar.com/1eschars.htm

+1

這解決了我的問題,謝謝:) – 2012-09-07 18:41:16

+0

解決了我的問題! – 2016-03-24 21:35:48

12

NSJSONSerialization就在角落裏。將NSString轉義爲Javascript字符串文字是hard並且可以很容易地做錯。 (JSONKit使用代碼行來處理它https://github.com/johnezang/JSONKit/blob/82157634ca0ca5b6a4a67a194dd11f15d9b72835/JSONKit.m#L1423

下面是一個小類別的方法來逃避NSString對象。

#import "NSString+JavascriptEscape.h" 

@implementation NSString (JavascriptEscape) 

- (NSString *)stringEscapedForJavasacript { 
    // valid JSON object need to be an array or dictionary 
    NSArray* arrayForEncoding = @[self]; 
    NSString* jsonString = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:arrayForEncoding options:0 error:nil] encoding:NSUTF8StringEncoding]; 

    NSString* escapedString = [jsonString substringWithRange:NSMakeRange(2, jsonString.length - 4)]; 
    return escapedString; 
} 

@end 

此外,有一點需要注意,您必須在javascript函數的參數中使用雙引號。例如,

NSString *javascriptCall = 
    [NSString stringWithFormat:@"MyJavascriptFunction(\"%@\")", escapedString]; 

[self.webView stringByEvaluatingJavaScriptFromString:javascriptCall]; 
+0

工作就像一個魅力!唯一可以提到的是,這個轉義引用了雙引號,所以你應該在你的stringByEvaluatingJavaScriptFromString調用中使用雙引號。我在下面的答案中舉了一個例子。 – 2014-08-13 23:47:17

+0

謝謝,@ChrisPrince,只是將你的建議附加到答案上! – zetachang 2014-08-20 07:37:44

0

如果你需要一個解決方案將與擴展ASCII符號(例如拉丁符號)和/或Unicode工作,你可以使用這個:

- (NSString*) escapeStringForJavascript:(NSString*)input 
{ 
    NSMutableString* ret = [NSMutableString string]; 
    int i; 
    for (i = 0; i < input.length; i++) 
    { 
     unichar c = [input characterAtIndex:i]; 
     if (c == '\\') 
     { 
      // escape backslash 
      [ret appendFormat:@"\\\\"]; 
     } 
     else if (c == '"') 
     { 
      // escape double quotes 
      [ret appendFormat:@"\\\""]; 
     } 
     else if (c >= 0x20 && c <= 0x7E) 
     { 
      // if it is a printable ASCII character (other than \ and "), append directly 
      [ret appendFormat:@"%c", c]; 
     } 
     else 
     { 
      // if it is not printable standard ASCII, append as a unicode escape sequence 
      [ret appendFormat:@"\\u%04X", c]; 
     } 
    } 
    return ret; 
} 

我不知道該怎麼行爲的代碼點高於unichar可表示的代碼點。看起來像這樣的字符不能用JavaScript來表示。

0

這是上面@ zetachang的回答。你必須在javascript函數的參數中使用雙引號。例如,

NSString *javascriptCall = 
    [NSString stringWithFormat:@"MyJavascriptFunction(\"%@\")", escapedString]; 
[self.webView stringByEvaluatingJavaScriptFromString:javascriptCall]; 
0

我會使用NSJSONSerialization將字符串轉換成JSON數組,然後粘貼生成的JSON字符串轉換爲JavaScript函數的參數。這樣我就不必擔心JSON字符串是包含在單引號還是雙引號內。

NSString* inputString = ... // your raw string to escape 
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:@[inputString] options:0 error:nil]; 
NSString* jsString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; 
NSString* jsScript = [NSString stringWithFormat:@"yourFunction(%@[0])",jsString]; 
// then pass jsScript to a JavaScript interpreter