はじめに
iOS Second Stage Advent Calendar20日目の記事です。
個人的には7記事目になります。
本題
Markdownを描画するライブラリを見つけたので、それを使用してQiitaの記事を用事するサンプルをつくってみました。
ライブラリはmdiep/MMMarkdownです。
サンプルプロジェクトは以下においておいきました。
AdventCalendar2015/SampleMMMarkdown at master · ryokosuge/AdventCalendar2015
スクリーンショット
こんな感じで表示できました。
導入
MMMarkdown
はCarthage
か自分でコピーするとのことなのでCarthage
を使用して導入しました。
Carthage
での導入方法などは世にたくさん出ているので、そちらを参考にしてください。
ちなみに今回使ったライブラリは以下になります。
## Himotoki
## source: https://github.com/ikesyo/Himotoki
github "ikesyo/Himotoki" ~> 1.3
## Alamofire
## source: https://github.com/Alamofire/Alamofire
github "Alamofire/Alamofire" ~> 3.0
## BrightFutures
## source https://github.com/Thomvis/BrightFutures
github "Thomvis/BrightFutures" ~> 3.2
## MMMarkdown
## source https://github.com/mdiep/MMMarkdown
github "mdiep/MMMarkdown"
最近Himotoki
を使うのが自分の中でのブームになっています。
ソースコード
Qiita
のAPIから記事のMarkdownの値が取得できるので、それを使ってやりました。
Himotokiを使ってレスポンスを構造体に変換
以下はQiita
APIから取得できるレスポンスを保持する構造体です。
import Foundation
import Himotoki
struct TagResponse: Decodable {
let name: String
let versions: [String]
static func decode(e: Extractor) throws -> TagResponse.DecodedType {
return try TagResponse(name: e <| "name", versions: e <|| "versions" )
}
}
struct UserResponse: Decodable {
let description: String?
let facebookID: String?
let followeesCount: Int
let followersCount: Int
let githubLoginName: String?
let id: String
let itemsCount: Int
let linkedinID: String?
let location: String?
let name: String
let organization: String?
let permanentID: Int
let profileImageURL: String
let twitterScreenName: String?
let websiteURL: String?
static func decode(e: Extractor) throws -> UserResponse.DecodedType {
return try UserResponse(description: e <|? "description", facebookID: e <|? "facebook_id", followeesCount: e <| "followees_count", followersCount: e <| "followers_count", githubLoginName: e <|? "github_login_name", id: e <| "id", itemsCount: e <| "items_count", linkedinID: e <|? "linkedin_id", location: e <|? "location", name: e <| "name", organization: e <|? "organization", permanentID: e <| "permanent_id", profileImageURL: e <| "profile_image_url", twitterScreenName: e <|? "twitter_screen_name", websiteURL: e <|? "website_url")
}
}
struct ItemResponse: Decodable {
let renderedBody: String
let body: String
let coediting: Bool
let createdAt: String
let id: String
let privateItem: Bool
let tags: [TagResponse]
let title: String
let updatedAt: String
let URL: String
let user: UserResponse
static func decode(e: Extractor) throws -> ItemResponse.DecodedType {
return try ItemResponse(renderedBody: e <| "rendered_body", body: e <| "body", coediting: e <| "coediting", createdAt: e <| "created_at", id: e <| "id", privateItem: e <| "private", tags: e <|| "tags", title: e <| "title", updatedAt: e <| "updated_at", URL: e <| "url", user: e <| "user")
}
}
ItemResponse
の中のbody
の値が投稿のMarkdownテキストになっています。
詳しくはQiita API v2 ドキュメントを参照ください。
ではそれを描画するのに MMMarkdownを使用してみます。
Markdownの描画
以下のページを参考にしてやってみました。
描画にはUITextView
を使用しています。
それのソースコードは以下になります。
import UIKit
import MMMarkdown
class DetailViewController: UIViewController {
static func instantiateViewControllerWithItem(item: ItemResponse) -> DetailViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewControllerWithIdentifier("DetailViewController") as! DetailViewController
viewController.item = item
return viewController
}
@IBOutlet weak var textView: UITextView!
private var item: ItemResponse!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setupView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
/// MARK: - private methods.
extension DetailViewController {
private func setupView() {
if let htmlString = try? MMMarkdown.HTMLStringWithMarkdown(item.body) {
let style = "<style>img { max-width: 300px; height: auto; }</style>\n"
let body = style + htmlString
print(body)
if let data = body.dataUsingEncoding(NSUnicodeStringEncoding) {
let attribute = [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType]
if let attributeText = try? NSAttributedString(data: data, options: attribute, documentAttributes: nil) {
textView.attributedText = attributeText
}
}
}
textView.editable = false
}
}
DetailViewController
のsetupView()
の中でMarkdownを表示するテキストに変換しています。
これだけで表示することができました。
余談
let style = "<style>img { max-width: 300px; height: auto; }</style>\n"
を追加しているのは 画像がそのままのサイズで表示されているからです。
比率を保ったまま、表示するので適当に設置してみました。
あとUITextView
ですが、かなり色々できるクラスになっています。
以下のページがわかりやすく紹介してくれているので参考にするといいかと思います。
iOS - [Objective-C] HTMLを使って文章をスタリングする - Qiita
終わりに
Markdownを返してくるサービス(API)ってあまり見かけませんが、自社サービスとか社内サービスとかにはいいかもですね。
以上になります。