Qiita の記事の閲覧数とLGTMの数を表示するiOSアプリを作成


この記事の内容について

Open-Source Source code / オープンソース: https://github.com/mszmagic/Qiita-Contribution-Counter

この記事では、いくつかのヒントや私がアプリで使用した技術について説明しています。どちらかというとケーススタディのようなものです。

  • ローカルデバイス上でユーザーのトークンを保存する
  • 既存のウェブクッキーを使用してモバイルアプリケーションにユーザーをログインさせる
  • URLSession を使用して GET requests を作る
  • Swift でJSONレスポンスを解析する
  • リモートサーバーから画像をロードする

もちろん、ここで私はすでにあるものを再発明しませんでした、いくつかの既存のオープンソースフレームワークを使用しました。記事の次の部分でそれについて紹介します。

概要

Githubと同じように Qiita コントリビューションを表示したかったのです。

そこで次のことができるオープンソースiOSアプリを作りました。

1.各記事の合計読み取り回数と読み取り回数を提供する

2.各記事の合計 LGTMs と views を提供する

3.Githubに似たコントリビューションブロックを表示して、当月内に記事を公開した日を表示する

コード構造

View Controller

ここで、ユーザーは Qiita APIページに進む をクリックして、新しいAPIトークンを作成できます。Safariのクッキーを自動的に使用することにご注意ください。

ASWebAuthenticationSession

ユーザーの既存のブラウザーセッションのクッキーをここで利用できるよう、ASWebAuthenticationSession を用います。そうすればユーザーは再度ログインしなくてもよくなります。

guard let authURL = URL(string: "https://qiita.com/settings/tokens/new") else { return }
let session = ASWebAuthenticationSession(url: authURL, callbackURLScheme: "")
{ callbackURL, error in
    // Handle the callback.
}
session.presentationContextProvider = self
session.start()

また、presentationContextProvider をセットアップして、 ASWebAuthenticationSession がビューを表示する場所を認識できるようにする必要があります。

/*
 ASWebAuthenticationSession がどこにビューを表示すべきか判断するためです
 */
extension ViewController: ASWebAuthenticationPresentationContextProviding {
    func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
        return view.window!
    }
}

ユーザーのトークンをキーチェーンに保存して、次回ユーザーがトークン値を再度入力する必要がないようにします

通常、アプリは機密情報(トークンなど)をキーチェーンに保存します。キーチェーンの使用に関するAppleの公式ドキュメントは以下のとおりです:https://developer.apple.com/documentation/security/keychain_services

キーチェーンサービスを使用するにはある程度のコードが必要なので、私はGithub上のオープンソースのキーチェーンヘルパーを使用しました。

let keychain = KeychainSwift()
keychain.set(tokenTextField.text ?? "", forKey: "qiitaToken")
tokenTextField.text = keychain.get("qiitaToken") ?? ""

userTableView

リモート画像フェッチ

ここでは、Kingfisher というオープンソースのフレームワークを使用しました。

@IBOutlet weak var profileImageView: UIImageView!
//画像をダウンロードして読み込みます
if let imagePath = profileImagePath,
    let convertedURL = URL(string: imagePath) {
    DispatchQueue.main.async {
        self.profileImageView.kf.setImage(with: convertedURL)
    }
}
self.profileImageView.kf.setImage(with: convertedURL)

requestHelper.swift

ここでは、URLSession を使ってリクエストしています:

let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil)

guard let URL = URL(string: "https://qiita.com/api/v2/authenticated_user/items") else {
    delegate?.onTaskFailed(reason: "URL convertion failed!")
    return
}

var request = URLRequest(url: URL)
request.httpMethod = "GET"

// Headers

request.addValue("Bearer \(userID ?? "")", forHTTPHeaderField: "Authorization")

/* Start a new Task */
let task = session.dataTask(with: request, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) -> Void in
    if let httpResponse = response as? HTTPURLResponse {
        let statusCode = httpResponse.statusCode
        if error == nil && statusCode >= 200 && statusCode < 400 {
            //成功
            let allItems = try! JSON(data: data!).array
            for item in allItems ?? [] {
                if let id = (item.dictionary?["id"])?.stringValue {
                    self.fetchIndividualArticle(id: id)
                }
            }
            return
        }
    }
    // 失敗
    self.delegate?.onTaskFailed(reason: error?.localizedDescription ?? "Unknown error. Please check your token and try again.")
})

task.resume()
session.finishTasksAndInvalidate()

受信結果を解析:

if let fetchedData = data {
    if let parsedData = try? JSON(data: fetchedData).dictionary {
        //ユーザー名
        let name = parsedData["name"]?.stringValue
        //説明 description
        let description = parsedData["description"]?.stringValue
        //プロフィール画像のURLパス
        let profileImage = parsedData["profile_image_url"]?.stringValue
        //
        completionHandler(profileImage, name, description, nil)
    }
}

ここでは、SwiftyJSON というオープンソースのフレームワークを使用しました。

Githubと同じように Qiita コントリビューションを表示したかったのです。

ここでは、LSHContributionView というオープンソースのフレームワークを使用しました。


Twitter @MszPro

私の公開されているQiita記事のリストをカテゴリー別にご覧いただけます。