Sparkleを使って自動アップデート確認ボタンを実装する

はじめに

macosアプリを開発するにあたって自動アップデート確認を実装したかった。 それ用のライブラリっぽい Sparkle を利用した。 圧倒的に詰まったし次忘れそうなので手順をメモ。 ついでに同じ内容で困ってる人に届け。

Sparkle: open source software update framework for macOS

動作環境

  • Xcode: Version 10.0 (10A255)
  • Sparkle: 1.21.2

手順

Podfileに追加

  • Podfile に追記します
pod 'Sparkle'
  • pod install を実行

更新をチェックボタンを追加

  • storyboard, xibObject を追加 f:id:Qsk:20190106181338p:plain

  • 追加した objectcustom classUSUpdater にする f:id:Qsk:20190106181800p:plain

  • 更新を確認するボタンを追加して object と紐付ける

    • checkForUpdate を選択 f:id:Qsk:20190106182024p:plain

画面の設定は以上です

SUPublicEDKeyを生成

  • {project path}/Pods/Sparkle/bin/generate_keys を実行
sparkleSample kyusuke$ Pods/Sparkle/bin/generate_keys
This tool uses macOS Keychain to store the Sparkle private key.
If the Keychain prompts you for permission, please allow it.
OK! Read the existing key saved in the Keychain.

In your app's Info.plist set SUPublicEDKey to:
isfUDYEDJDbsjshajfasd72h26JuhfhUHBDY+ytc/58=
# ↑を使います

Info.plistを編集

  • SUFeedURLを設定

    • バージョンの確認に利用
    • 以降の手順で作る appcast.xml を配置するURLを入力します
    • 置く場所が未定ならgithub pages に置くのが良いと思います
  • SUPublicEDKey

    • 先程出した値を入力します(例だとisfUDYEDJDbsjshajfasd72h26JuhfhUHBDY+ytc/58=)

f:id:Qsk:20190106183546p:plain

appをexport

  • Product → Archive →Distribute App → Copy App でappをexport
  • exportしたフォルダ内の.appzipする

f:id:Qsk:20190106183942p:plain

appcast.xmlを出力

  • {project path}/Pods/Sparkle/bin/generate_appcast {archived folder} を実行
sparkleSample kyusuke$ Pods/Sparkle/bin/generate_appcast ~/Desktop/sparkleSample1.1/
Written /Users/kyusuke/Desktop/sparkleSample1.1/sparkleSample.xml based on 1 updates
  • 出力したappcast.xmlenclosuresparkle:edSignature の記載があるか確認
    • なければ {project path}/Pods/Sparkle/bin/sign_update {archived folder/appName.zip} を実行して appcast.xmlenclosure に追記
sparkleSample kyusuke$ Pods/Sparkle/bin/sign_update ~/Desktop/sparkleSample1.1/sparkleSample.zip
sparkle:edSignature="xxxxxxxxxxxxxxxxxxxxxxxxxxxx" length="11111111"
  • appcast.xmlをアップロード
    • appを起動して更新確認ボタン押下時に所定のURLからxmlを見てバージョン確認してくれるようになります

その他

今回の実装例では発生しなかったけど、疎通周りで結構エラーが出たのでその際の対応

A server with the specified hostname could not be found.

  • App Transport Security Settings の設定を Info.plist に追加
    • Allow Arbitrary LoadsYes にする f:id:Qsk:20190106185330p:plain

launch path not accessible

  • {appName.entitlements} の com.apple.security.app-sandboxfalse にする
    • 今回だとsparkleSample.entitlements
    • このやり方が正しいのかはだいぶ怪しい
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.files.user-selected.read-only</key>
    <true/>
    <key>com.apple.security.app-sandbox</key> <!-- これと -->
    <false/> <!-- これと -->
</dict>
</plist>

所感

sparkleの日本語情報が基本的に古くて、当時と今で認証方法の種類とかファイル名とか細かいところが変わってて結構ハマった。 macosの情報があんまりないので機会があれば書いていきたい。

実装例

github.com

releaseから1.0.zipを落としてupdateを試せると思う

参考URL

ありがとうございました

qiita.com

macOS で ネットからURLでダウンロードするコードが動かなくなり焦って調べてみた - Qiita

macアプリ XCode9.4.1より特定のフォルダにアクセスできない問題の回避方法 | まつゆう (@YutakaMatsui)