LoginSignup
0
1

More than 3 years have passed since last update.

[SwiftUI]正規表現によるネイティブUIでのマルチメディア

Last updated at Posted at 2020-06-28

実現するもの

全体のイメージ

multimedia.gif

詳しく見ましょう

speciesData.json
"detailText": [
    "コガタペンギンは保護色があり、青い背中は上から見れば海と同じに見え、白い腹は下の捕食者と獲物を迷惑させることができます。したがって、夜に波から上陸するとき、海岸に打ち寄せる白い波が突然立ち上がって、コガタペンギンの群れになったように見えます。",
    "これはまさにおとぎ話のようで、英語では「フェアリーペンギン(Fairy Penguin)」とも呼ばれています。",
    "<image>02</image>",
    "<caption>夜に帰ってくるコガタペンキンの群れ。画像:Phillipislandtourism / Wikimedia Commons</caption>",
    "コガタペンギンの平均寿命は6〜7年くらいですが、飼育下では20年を超えることもあります。",
]

上記のコードで生成されたのはこちら⬇️

このように、文字列(String)だけのデータをもとに、

コンテンツ 記述
本文(Text) 本文
画像(Image) <image>画像番号</image>
画像の説明文(Text) <caption>説明文</caption>

が混在しているマルチメディアのコンテンツをネイティブUIで自動生成します。

ここは例示なので、コンテンツの種類と記述方法は簡単にカスタマイズできます。

実装方法

正規表現で記述を認識

正規表現に詳しくなくても大丈夫です。
まず、ある文字列が指定したパターンと一致しているか、を教えてくれるものとして覚えましょう。

例えば、"<image>"で始まり、"</image>"で終わる文字列であるか、ということを判断してくれます。

パターンの定義

RegularExpression.swift
enum RegexPattern: String {
    case image = "^<image>.*</image>$"
    case caption = "^<caption>.*</caption>$"
}

"^<image>.*</image>$"というパターンは、
"<image>"で始まり、"</image>"で終わることを意味しています。
この部分を書き換えれば、記述方法をカスタマイズできます。

一致判断とタグ削除

RegularExpression.swift
import Foundation

extension String {
    //正規表現の一致判断
    func match(pattern:RegexPattern) -> Bool {
        let pattern = pattern.rawValue
        let regex = try! NSRegularExpression(pattern:pattern)
        return regex.firstMatch(in:self, range:NSRange(self.startIndex..., in:self)) != nil
    }

    //両端のタグの削除
    func strip() -> String {
        let lstrip = self.replacingOccurrences(of:"^<\\w+>", with:"", options:NSString.CompareOptions.regularExpression, range:self.range(of:self))
        return lstrip.replacingOccurrences(of:"</\\w+>$", with:"", options:NSString.CompareOptions.regularExpression, range:lstrip.range(of:lstrip))
    }
}

ここでは、呼び出しやすくするために、String型のメソッドとして実装します。

ネイティブUIを生成

SpeciesDetail.swift
import SwiftUI

struct SpeciesDetail: View {
    var species: Species

    var body: some View {
        ScrollView {
            VStack {
                //文字列ごと処理
                ForEach(self.species.detailText, id: \.self) { text -> AnyView in
                    //imageのパターンと一致した場合
                    if text.match(pattern: .image) {
                        return AnyView(
                            //SwiftUIのImageを利用し、画像コンテンツの表示をカスタマイズ
                            Image("\(self.species.imageName)_\(text.strip())")
                            .resizable()
                            .scaledToFit()
                        )
                    //captionのパターンと一致した場合
                    } else if text.match(pattern: .caption){
                        return AnyView(
                            //SwiftUIのTextを利用し、画像の説明文の表示をカスタマイズ
                            Text(text.strip())
                            .foregroundColor(Color.gray)
                            .font(.custom("Baskerville", size: 16))
                        )
                    //どのパターンとも一致しない場合
                    } else {
                        return AnyView(
                            //SwiftUIのTextを利用し、本文の表示をカスタマイズ
                            Text(" " + text)
                            .padding(.top, 18)
                            .font(.custom("Baskerville", size: 20))
                            .lineSpacing(12)
                            .fixedSize(horizontal: false, vertical: true)
                        )
                    }
                }
            }
            .padding()
        }
    }
}

struct SpeciesDetail_Previews: PreviewProvider {
    static var previews: some View {
        SpeciesDetail(species: speciesData[0])
    }
}

フルコード

以上は自分のアプリの一部として実装しています。
詳しくはこちら(GitHubへ)をご覧ください。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1