【Swift】Tips: あると便利だったextension達(記法編)

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

モバイルアプリサービス部の中安です。

最近ブログを書けていなかったので、小ネタを少しばかり・・・。

アプリを作ってきた際に、あるとなかなか便利だった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

これでキャメル記法とスネーク記法の相互互換ができるようになりました。