この記事の内容について

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
というオープンソースのフレームワークを使用しました。