ottijp blog

iOS+Swiftで,HTML文字列をRTF(リッチテキスト)に変換してペーストボードにコピーする方法

  • 2023-12-04

これはInfocom Advent Calendar 2023 4日目の記事です.

私の作ったアプリ「Copy as Link」で,HTML形式の文字列をRTF(リッチテキスト)としてペーストボードにコピーする機能があるのですが,この実装を説明します.

環境

  • Xcode: 15.0.1
  • iOS: 15.0+

実装例

HTMLを編集するTextEditorと変換を実行するButtonを持つビューを作りました.

import SwiftUI
import UniformTypeIdentifiers

struct ContentView: View {
  @State private var htmlText = "<font size=\"30px\">30px text</font><br>\n<font color=\"red\">red text</font><br>\n<a href=\"https://blog.ottijp.com\">my blog</a>"

  var body: some View {
    VStack {
      Text("write html")
      // HTMLを編集するテキストエディタ
      TextEditor(text: $htmlText)
        .font(.system(size: 20))
        .border(.foreground)
      // 変換を実行するボタン
      Button(action: {
        copyAsRichText()
      }) {
        Text("copy as rich text")
      }
    }
    .padding()
  }

  func copyAsRichText() {
    // convert html to rich text
    guard let htmlData = htmlText.data(using: .utf8),
          let attrString = try? NSMutableAttributedString(
            data: htmlData,
            options: [.documentType: NSAttributedString.DocumentType.html,
                      .characterEncoding: String.Encoding.utf8.rawValue
            ],
            documentAttributes: nil),
          let rtfData = try? attrString.data(
            from: .init(location: 0, length: attrString.string.count),
            documentAttributes: [.documentType: NSAttributedString.DocumentType.rtf])
    else {
      print("invalid html")
      return
    }

    // copy to pasteboard
    let pasteBoard = UIPasteboard.general
    pasteBoard.setData(rtfData, forPasteboardType: UTType.rtf.identifier)

    print("copied")
  }
}

#Preview {
  ContentView()
}

見た目はこのようになります.

app

「copy as rich text」を押してPagesにコピーすると,このようになります.

pages

説明

copyAsRichText()関数の中で次のことをしています.

  • HTMLの文字列をData型に変換
  • Data型のHTMLをNSMutableAttributedString型に変換
  • NSMutableAttributedString型のHTMLをData型のRTFに変換
  • Data型のRTFをペーストボードにコピー

ottijp
都内でアプリケーションエンジニアをしています
© 2024, ottijp