[Swift] あると便利だったextension達 記法編
はじめに
モバイルアプリサービス部の中安です。
最近ブログを書けていなかったので、小ネタを少しばかり・・・。
アプリを作ってきた際に、あるとなかなか便利だったextensionをボチボチとご紹介していければと思っています。 アプリの目的に合わせてやりかえる必要があったり、もっとよい実装があるかもしれませんが、何かの役に立てば光栄です。
今回は文字列の記法編です。
APIのキーやパラメータ、DBの論理名、その他諸々とスネーク記法を使ったり、キャメル記法を使ったりというシーンは多いかと思いますが、 そういう時に記法の変換を行ってくれるメソッドを準備しておけば色々と助かることも多いでしょう。
文字列をアッパーキャメル記法に
念のための説明ですが、「アッパーキャメル記法」とは単語の最初の文字を大文字にして、単語間には何も入れない(アンダースコアやスペースがない)記法のことです。 Swiftのクラスなどのシンボル名などは、こちらの命名規則ですね。
今回はキャメル記法(後述)からアッパーキャメル記法に変換するという想定で extension を作ってみます。
extension String { func toUpperCamel() -> String { return capitalized.replacingOccurrences(of: "_", with: "") } }
シンプルに capitalized という便利な String の機能があります。 これとアンダースコアの置換を組み合わせることでシンプルに実現できます。
例えば、TwitterAPIの戻り値のJSONキー(抜粋)にこれを適用してみると
"protected".toUpperCamel() "followers_count".toUpperCamel() "created_at".toUpperCamel() "utc_offset".toUpperCamel() "time_zone".toUpperCamel() "geo_enabled".toUpperCamel() "contributors_enabled".toUpperCamel() "is_translation_enabled".toUpperCamel() "profile_background_image_url".toUpperCamel() "profile_use_background_image".toUpperCamel() "has_extended_profile".toUpperCamel() "default_profile_image".toUpperCamel() "follow_request_sent".toUpperCamel() "translator_type".toUpperCamel() "retweeted_status".toUpperCamel() "in_reply_to_screen_name".toUpperCamel() ↓ Protected FollowersCount CreatedAt UtcOffset TimeZone GeoEnabled ContributorsEnabled IsTranslationEnabled ProfileBackgroundImageUrl ProfileUseBackgroundImage HasExtendedProfile DefaultProfileImage FollowRequestSent TranslatorType RetweetedStatus InReplyToScreenName
このようになります。
文字列をキャメル記法に
「キャメル記法」とは、前述のアッパーキャメル記法のルールに則りますが、一番最初の文字だけ小文字になる記法です。 Swiftの変数名などは、こちらの命名規則ですね。
extension String { func toCamel() -> String { if isEmpty { return "" } let range = NSMakeRange(0, 1) let ns = toUpperCamel() as NSString return ns.replacingCharacters(in: range, with: ns.substring(with: range).lowercased()) } }
前項のアッパーキャメル生成を元に、最初の一文字を lowercase にするだけです。
"protected".toCamel() "followers_count".toCamel() "created_at".toCamel() "utc_offset".toCamel() "time_zone".toCamel() "geo_enabled".toCamel() "contributors_enabled".toCamel() "is_translation_enabled".toCamel() "profile_background_image_url".toCamel() "profile_use_background_image".toCamel() "has_extended_profile".toCamel() "default_profile_image".toCamel() "follow_request_sent".toCamel() "translator_type".toCamel() "retweeted_status".toCamel() "in_reply_to_screen_name".toCamel() ↓ protected followersCount createdAt utcOffset timeZone geoEnabled contributorsEnabled isTranslationEnabled profileBackgroundImageUrl profileUseBackgroundImage hasExtendedProfile defaultProfileImage followRequestSent translatorType retweetedStatus inReplyToScreenName
このようになります。
文字列をスネーク記法に
「スネーク記法」とは、文字列は全て小文字で表現され、単語と単語はアンダースコアで繋げていく記法です。 先ほどから登場しているTwitterAPIの戻り値の各JSONキーもそうであるように、WebAPIなどでは多用されている記法です。
キャメル記法(前述)からスネーク記法に変換するという想定で extension を作ります。
extension String { func toSnake() -> String { let pattern = "(?<=\\w)([A-Z])" guard let reg = try? NSRegularExpression(pattern: pattern, options: []) else { return self } let mutable = NSMutableString(string: self) let range = NSMakeRange(0, self.count) reg.replaceMatches(in: mutable, options: [], range: range, withTemplate: "_$1") return (mutable as String).lowercased() } }
正規表現を使用して、文字列の途中で大文字から始まる単語の先頭にアンダースコアを付け、 lowercase へと変換しています。
"createdAt".toSnake() "utcOffset".toSnake() "timeZone".toSnake() "geoEnabled".toSnake() "contributorsEnabled".toSnake() "isTranslationEnabled".toSnake() "profileBackgroundImageUrl".toSnake() "profileUseBackgroundImage".toSnake() "hasExtendedProfile".toSnake() "defaultProfileImage".toSnake() "followRequestSent".toSnake() "translatorType".toSnake() "retweetedStatus".toSnake() "inReplyToScreenName".toSnake() ↓ created_at utc_offset time_zone geo_enabled contributors_enabled is_translation_enabled profile_background_image_url profile_use_background_image has_extended_profile default_profile_image follow_request_sent translator_type retweeted_status in_reply_to_screen_name
これでキャメル記法とスネーク記法の相互互換ができるようになりました。