Terrarium

いわゆる掃き溜めの ありふれた有象無象

SwiftでDropboxを利用するメモ

(注意:ほぼ自分用のメモです)

Dropboxを使う理由

現在自分用の簡単な消費管理アプリを作りたいと考えており,そのデータの保存先を色々検討していました. 次のような選択肢が考えられます.

  • AWSとかAzureとかのDBを利用
  • 自前のサーバのDBを利用
  • UserDefaultに格納
  • Google Spreadsheet
  • Dropbox

前者2つはコストがかかるので見送り,UserDefaultに全部しまってしまうのもアプリらしくない(?),Google SpreadsheetにはSwiftのライブラリがない(自分でAPIを叩く必要)などの理由から,今回はDropboxを利用してみることにしました.

SwiftyDropbox

DropboxをSwiftから使うためのライブラリです.

github.com

使い方は上のREADMEに書いてある通りになります.

インストールなど

行なった操作は次の通り.

  1. pod経由でインストール
  2. Dropboxのサイトでcreate app -> API_KEYの取得
  3. Info.plist編集その1 LSApplicationQueriesSchemes
  4. Info.plist編集その2 CFBundleURLTypes

ここでInfo.plistにdb-<APP_KEY>という形で値を指定するのですが,プロジェクトをGithubなどに公開したときにこれはAPP_KEYは漏れても大丈夫なのか?と感じました(自分は初心者なのでわからないのですが,多分SECRET_KEYの方が漏れなければ大丈夫なのかな,と考えてます,公開するときまでには調べなければ)

コーディング

基本的には次の3つを記述すれば動作します.

  1. AppDelegateのapplication(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool内で
DropboxClientsManager.setupWithAppKey("<APP_KEY>")

これでAPP_KEYを登録します.

  1. ボタンを押した時などのメソッド内で
DropboxClientsManager.authorizeFromController(UIApplication.shared,
                                                  controller: self,
                                                  openURL: { (url: URL) -> Void in
                                                    UIApplication.shared.openURL(url)
                                                  })

するとボタンを押すとログイン画面が出るようになります. ただこれだけだと最後のAllowを押してもブラウザが終了しません.

  1. AppDelegate内で
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    if let authResult = DropboxClientsManager.handleRedirectURL(url) {
        switch authResult {
        case .success:
            print("Success! User is logged into Dropbox.")
        case .cancel:
            print("Authorization flow was manually canceled by user!")
        case .error(_, let description):
            print("Error: \(description)")
        }
    }
    return true
}

を丸々追記. これで上記のログイン画面でAllowなどを押すと終了し,結果が返ってくるようになります.

  1. ファイルをアップロードするには,同様にボタンなどを押した時などのメソッド内で
if let client = DropboxClientsManager.authorizedClient {
    let fileData = "testing data example".data(using: String.Encoding.utf8, allowLossyConversion: false)!
    
    let request = client.files.upload(path: "/pocket_management/sample.txt", input: fileData)
        .response { response, error in
            if let response = response {
                print(response)
            } else if let error = error {
                print(error)
            }
        }
        .progress { progressData in
            print(progressData)
        }
} else {
    // error
    print("not logged in")
}

のようにやるのが良さそうです. clientの取得はControllerで1個用意しておくよりも毎回optional bindingで呼び出した方が良いのか…? (そのほうがエラー処理が書きやすそうに思える)

終わりに

本当にメモですが書いておきました. せっかくアプリを作るのでデザインからやったり色々試してみようと思います.