Cocoa アプリで非標準の URL を開く
-
09-06-2019 - |
質問
私が書いているアプリケーションには、次のようなコードがあります。
NSWorkspace* ws = [NSWorkspace sharedWorkspace];
NSString* myurl = @"http://www.somewebsite.com/method?a=%d";
NSURL* url = [NSURL URLWithString:myurl];
[ws openURL:url];
主な違いは、 マイURL 私の制御の及ばないどこかから来ます。URL 内の %d は完全に正しいわけではなく、URLWithString が失敗して返されることを意味します。 なし.
これに対処する「正しい」方法は何ですか?文字列を解析して引数を適切にエンコードする必要がありますか?それとも、Cocoa には、面倒な作業をすべてやってくれる賢い方法があるのでしょうか?
解決
これがまさにあなたが探しているものであるかどうかはわかりませんが、NSString には URL をサニタイズするメソッドがあります。
他のヒント
%d は URL の有効なコンポーネントではないため、ここでの動作は正しいと思います (% はエスケープですが、その後に 2 つの 16 進文字が続くことが想定されています)。
指定された URL をそのまま URL エンコードすることはできません。これを行うと、望ましくない /s と ?s もエンコードされてしまうからです。
そこで問題は、ここでの正しい動作は何でしょうか?
おそらくあなたはそれを次のようにしたいと思うでしょう...
http://www.somewebsite.com/method?a=%25d
(すなわち、% は URL 内の % のエンコードされたバージョンにエンコードされるため、メソッドが入力を取得すると、 a が %d に設定されていると見なされます)
それを行う「正しい」方法がないので、そのようなことを行うライブラリ関数はないと思います。あなたができる唯一の正しいことは、与えられたURLが無効であるというエラーメッセージを返すことです(URLWithStringと同じように)
入力を処理したい場合は、URL 内で 2 つの 16 進文字がすぐに続かない % 記号を検索し、その場合は % を %25 に置き換える必要があると思います。これは正規表現を使用すれば十分に可能ですが、URL に ASCII 文字セット以外の文字のエンコードされたバージョンが含まれ始めた場合は、さらに複雑になる可能性があると思います。
残念ながら、Apple が提供するものよりも賢くする必要があります。
stringByAddingPercentEscapesUsingEncoding:
これにより、無効な URL 文字がすべてエスケープされ、有効な「http://foo.com/hey%20dude/」が「http://foo.com/hey%2520dud/」になりますが、これは私たちが望むものではありません。 。
私は正しいことを行い、部分的にエンコードされた文字列などの奇妙な文字列を処理する NSURL カテゴリを作成しました。「http://foo.com/hey dude/i%20do%20it/」)。
コードは次のとおりです。
@interface NSURL (SmartEncoding)
+ (NSURL *)smartURLWithString:(NSString *)str;
@end
@implementation NSURL (SmartEncoding)
+ (NSURL *)smartURLWithString:(NSString *)str
{
CFStringRef preprocessed = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (CFStringRef)str, CFSTR(""), kCFStringEncodingUTF8);
if (!preprocessed)
preprocessed = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (CFStringRef)str, CFSTR(""), kCFStringEncodingASCII);
if (!preprocessed)
return [NSURL URLWithString:str];
CFStringRef sanitized = CFURLCreateStringByAddingPercentEscapes(NULL, preprocessed, NULL, NULL, kCFStringEncodingUTF8);
CFRelease(preprocessed);
NSURL *result = (NSURL*)CFURLCreateWithString(NULL, sanitized, NULL);
CFRelease(sanitized);
return [result autorelease];
}
@end
UTF8 でエンコードされた文字列と ASCII 文字列で正常に動作します。