質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.34%

  • Swift

    5048questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • iOS

    2957questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swiftで@(アットマーク)を%40(URLエンコード)に変換したい

解決済

回答 3

投稿 2017/12/05 20:22

  • 評価
  • クリップ 0
  • VIEW 87

u-ta

score 34

前提・実現したいこと

Swift4、iOSアプリで、@(アットマーク)をURLエンコードしたい。

入力されたLINEの友達URL

例: https://line.me/R/ti/p/@abcdefg

をopenURLする際に、@を%40にしないとLINEが正しく読み取れないため
@(アットマーク)をURLエンコードしたいのですが変換がうまくいきません。

発生している問題・エラーメッセージ

@をreplacingOccurrencesで%40へ置き換えると%40ではない値になる。
@は消えるが、withをうまく指定できません。

var base:String       = "https://line.me/R/ti/p/@abcdefg"
var replace:String    = base.replacingOccurrences(of:"@", with:"%40")
NSLog("replace 1 :\(replace)")
replace               = base.replacingOccurrences(of:"@", with:"%x")
NSLog("replace 2 :\(replace)")
replace               = base.replacingOccurrences(of:"@", with:"x")
NSLog("replace 3 :\(replace)")
replace 1 :https://line.me/R/ti/p/                                  0x0p+0bcdefg
replace 2 :https://line.me/R/ti/p/0abcdefg
replace 3 :https://line.me/R/ti/p/xabcdefg

replace1の空白はxcodeのコンソールのままです。

補足情報(言語/FW/ツール等のバージョンなど)

swift4

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

ピンポイントでの置換なら、

base.replacingOccurrences(of:"@", with:"%%40") //`%`はメタ文字
//=> https://line.me/R/ti/p/%40abcdefg

汎用的にURLエンコードしたいなら、

"@abcdefg".addingPercentEncoding(withAllowedCharacters: .alphanumerics)
//=> %40abcdefg

 訂正

メタ文字はメタ文字でも、NSLogのメタ文字でした。

var replace = base.replacingOccurrences(of: "@", with: "%40")
print("replace 1 :\(replace)")
//=> replace 1 :https://line.me/R/ti/p/%40abcdefg

これで変換自体は正しくできています。

おかしかったのはNSLogの使い方で、

NSLog("replace 1 :\(replace)") //これは
NSLog("replace 1 :https://line.me/R/ti/p/%40abcdefg") //これと同じ意味

なので、%40aという書式を指定していることになります。さらに引数の指定無し。
%aというのは浮動小数点の16進表記(?)だそうで、
空白 + 0x0p+0 + bcde =                                   0x0p+0bcdefg
という表示になってしまっていたのです。

正しくは、

NSLog("replace 1 :%@", replace)
//=> replace 1 :https://line.me/R/ti/p/%40abcdefg

となります。

投稿 2017/12/06 09:25

編集 2017/12/06 13:45

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/06 12:08

    ありがとうございます。
    ピンポイントでの置換にしました。

    urlQueryAllowedですマルチバイト対応をしていましたが@が対象とならないのですが
    alphanumericsだとhttps://などの置き換えられてしまったので、今回replacingOccurrencesを検討していました。

    メタ文字だったんですね。
    https://stackoverflow.com/questions/3439853/replace-occurrences-of-space-in-url
    をみて、通常の文字だと勘違いしてしまっていました。

    ありがとうございました。

    キャンセル

  • 2017/12/06 13:50 編集

    ん?と思って調べたら勘違いでした。回答に「訂正」を追記しました。

    ついでに、
    >>alphanumericsだとhttps://などの置き換えられてしまったので
    普通は丸ごとエンコードしないと思います。

    キャンセル

  • 2017/12/06 15:37

    ありがとうございます、

    NSLOGの見えかたの問題ということですね。
    当初の下記のコードにしてテストしています。
    var replace = base.replacingOccurrences(of: "@", with: "%40")


    >>alphanumericsだとhttps://
    文が足りてませんでした、パス区切りの/や?が変換されるので
    サーバー側などふくめて確認する必要がありるのかと考えていました。
    URLEncodeの種類?RFCなのかわかりませんがもろもろ影響調査が必要なのかと考えており、alphanumericsは使っていませんでした。


    AbsoluteURL文字列からURLを生成する際の文字チェック、変換処理(encodeするならどの文字を対象とするか?)などの王道的なものがわかっていません。

    キャンセル

+1

let allowed = CharacterSet
    .urlFragmentAllowed
    .subtracting(CharacterSet(charactersIn: "@"))

let replaced = base.addingPercentEncoding(withAllowedCharacters: allowed)


こうでしょうか?

投稿 2017/12/05 21:24

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/05 21:42

    ありがとうございます。
    いま移動中なので後ほど試してみます。


    replacingOccurrencesでできない理由というか
    そもそも使い方が違うのでしょうか?

    キャンセル

  • 2017/12/05 22:05

    たんに専用の関数があるのに使ってないことに違和感があっただけです。
    ちなみに手元ではreplacingOccurrencesを使っても問題がありませんでした。

    キャンセル

  • 2017/12/06 12:11

    メタ文字だと気づきませんでした。
    今回の問題はいただいた回答で解決しましたが
    マルチバイトや@などの対応方法をもう少し調べて見ます。

    キャンセル

0

withAllowedCharactersを調べて最適な方法を考えます。

let base:String       = "https://line.me/R/ti/p/@abcdefg/?q1=123&q2=あ"
var replace:String    = base.replacingOccurrences(of:"@", with:"%%40")
NSLog("replace 1 :\(replace)")
    replace     = base.addingPercentEncoding(withAllowedCharacters: .alphanumerics)!
NSLog("replace 2 :\(replace)")
    replace     = base.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
NSLog("replace 3 :\(replace)")
    let allowed = CharacterSet.urlFragmentAllowed.subtracting(CharacterSet(charactersIn: "@"))
    replace     = base.addingPercentEncoding(withAllowedCharacters: allowed)!
NSLog("replace 4 :\(replace)")
replace 1 :https://line.me/R/ti/p/%40abcdefg/?q1=123&q2=あ
replace 2 :https0X0P+00.0000000.000000line0.000000E+00me-4277374514952982788899796294912006593111872596699109871130058268368934249870917275884438706951811490737744992940320538145728883419978032083095270091847783243124681598621026781775093230743988129684695659598216213104477000370263221601824008509252482105344.000000R0.000000ti0.000000p0.000000                                  0x0p+0bcdefg0.0000000.000000q1  012323D0.000000E+003882
replace 3 :https://line.me/R/ti/p/@abcdefg/?q1=123&q2=0.000000E+003882
replace 4 :https://line.me/R/ti/p/                                  0x0p+0bcdefg/?q1=123&q2=0.000000E+003882

投稿 2017/12/06 12:06

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.34%

関連した質問

同じタグがついた質問を見る

  • Swift

    5048questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • iOS

    2957questions

    iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。