- 投稿日:2020-01-18T20:59:22+09:00
Swift Postman 導入(つまづいたところ全部)
Postman
APIとは
https://www.internetacademy.jp/it/programming/javascript/how-to-use-web-api.html
APIの導入はかなりめんどくさい・・らしい。
というのも自分はまだサンプルプログラム等でしかAPIを用いたことがない。
コードを書いていたときは、これ自分が欲しいAPI合っても導入で時間かかりそうだなぁとざっくり思ってました。本題
PostmanはそのAPIの構築をサポートするツールとのこと。
どれどれやってみよう。
(ちなみに一度は上記のめんどくさいやり方でやってみることが重要だとは思ってますhttps://qiita.com/dddisk/items/09b46c65434c117f1287)で表示される画面がこちら
とてもピンときませんね。
ということでまずはAPIについて学んでいきます
APIはHTTPのリクエスト、レスポンスとかを使う。ふむ。
https://qiita.com/r_fukuma/items/a9e8d18467fe3e04068e
- 投稿日:2020-01-18T20:47:31+09:00
【swift5】カウントダウンタイマーの実装
まずUIPickerViewで「何時間」「何分」「何秒」を選択してストップウォッチ作成。
そこからカウントダウンするのですが、セットした時間が全部秒になってしまっております。。。
60秒以内なら問題ないのですが1分30秒だと90秒のような感じ。
カップラーメンに使ったり筋トレのタイマーなんかにはいいのではないでしょうか。
2020年1月18現在ではこんな感じですが、修正したいと思います。
デザイン
ソース全体
import UIKit class TimerViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource { @IBOutlet weak var pickerLabel: UILabel! @IBOutlet weak var pickerView: UIPickerView! @IBOutlet weak var start: UIButton! var timer:Timer = Timer() var count:Int = 0 let dataList = [[Int](0...24), [Int](0...60), [Int](0...60)] override func viewDidLoad() { super.viewDidLoad() //「時間」のラベルを追加 let hStr = UILabel() hStr.text = "時間" hStr.sizeToFit() hStr.frame = CGRect(x: pickerView.bounds.width/4 - hStr.bounds.width/2, y: pickerView.bounds.height/2 - (hStr.bounds.height/2), width: hStr.bounds.width, height:hStr.bounds.height) pickerView.addSubview(hStr) //「分」のラベルを追加 let mStr = UILabel() mStr.text = "分" mStr.sizeToFit() mStr.frame = CGRect(x: pickerView.bounds.width/2 - mStr.bounds.width/2, y: pickerView.bounds.height/2 - (mStr.bounds.height/2), width: mStr.bounds.width, height: mStr.bounds.height) pickerView.addSubview(mStr) //「秒」のラベルを追加 let sStr = UILabel() sStr.text = "秒" sStr.sizeToFit() sStr.frame = CGRect(x: pickerView.bounds.width*3/4 - sStr.bounds.width/2, y: pickerView.bounds.height/2 - (sStr.bounds.height/2), width: sStr.bounds.width, height: sStr.bounds.height) pickerView.addSubview(sStr) } //コンポーネントの個数を返すメソッド func numberOfComponents(in pickerView: UIPickerView) -> Int { return dataList.count } //コンポーネントに含まれるデータの個数を返すメソッド func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return dataList[component].count } //サイズを返すメソッド func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat { return pickerView.bounds.width * 1/4 } //データを返すメソッド func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView { let pickerLabel = UILabel() pickerLabel.textAlignment = NSTextAlignment.left pickerLabel.text = String(dataList[component][row]) return pickerLabel } @IBAction func startCountButton(_ sender: Any) { timer.invalidate() count = dataList[0][pickerView.selectedRow(inComponent: 0)] * 60 * 60 + dataList[0][pickerView.selectedRow(inComponent: 1)] * 60 + dataList[0][pickerView.selectedRow(inComponent: 2)] timer = Timer.scheduledTimer(timeInterval: 1, target:self, selector:#selector(countDown), userInfo:nil, repeats:true) } @IBAction func reset(_ sender: Any) { count = 0 pickerLabel.text = "カウントダウン終了" } //タイマーから呼び出されるメソッド @objc func countDown(){ count -= 1 if(count > 0) { pickerLabel.text = "残り\(count)秒です。" } else { pickerLabel.text = "カウントダウン終了" timer.invalidate() } } }参考サイト
ちょいと記事が古かった
https://hajihaji-lemon.com/smartphone/swift/uipickerview_countdown/
- 投稿日:2020-01-18T16:37:38+09:00
【swift】強制アップデート機能用ライブラリsirenの解説と実装
環境
xcode 11.3
swift 5.1.3
CocoaPods 1.8.4手順
完成形
CocoaPodsによるライブラリのインストール
以下を追加後、ターミナルで
pod install
を実行Podfilepod 'Siren'コードの記述
AppDeledate.swiftclass AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // sirenの強制アップデート設定用関数 forceUpdate() return true } // 途中省略 } // 以下、追記 private extension AppDelegate { func forceUpdate() { let siren = Siren.shared // 言語を日本語に設定 siren.presentationManager = PresentationManager(forceLanguageLocalization: .japanese) // ruleを設定 siren.rulesManager = RulesManager(globalRules: .critical) // sirenの実行関数 siren.wail { results in switch results { case .success(let updateResults): print("AlertAction ", updateResults.alertAction) print("Localization ", updateResults.localization) print("Model ", updateResults.model) print("UpdateType ", updateResults.updateType) case .failure(let error): print(error.localizedDescription) } } // 以下のように、完了時の処理を無視して記述することも可能 // siren.wail() } }sirenの解説
使用例
以下の使用例まとめをみると、どうやって使えばいいのかがわかりやすい。
PresentationManagerとは
表示されるアラートの設定を行うものという認識。
呼び出し時に引数として渡すことで設定できるのは、以下のプロパティたち。
- appName: アプリ名
- alertTitle: アラートのタイトル
- alertMessage: アラートのメッセージ
- updateButtonTitle: 更新ボタンのタイトル
- nextTimeButtonTitle: 次回更新ボタンのタイトル
- skipButtonTitle: スキップボタンのタイトル
- forceLanguageLocalization forceLanguage: 言語
基本的に、言語を日本語に設定すれば、他は特にいじらなくても大丈夫そう。
何も指定しない場合は、iPhoneの本体の設定言語で表示されるため、日本人以外にもターゲティングしてる場合はそちらで。コードは以下。
RuleManagerとは
強制アップデートのルールを設定するものという認識。
ruleに関して
更新頻度の種類
.immediately .daily .weekly 毎アプリ起動時 1日1回 1週間に1回 アラートタイプの種類
.force .optional .skip .none 更新ボタンのみ 更新ボタン・次回起動時ボタン 更新ボタン・次回起動時ボタン・このアップデートをスキップするボタン アラートを表示しない 更新頻度・アラートタイプの組み合わせ表現
annoying critical default hinting persistent relaxed 更新頻度 .immediately .immediately .daily .weekly .daily .weekly アラートタイプ .option .force .skip .option .option .skip 一括で指定する場合
RulesManager(globalRules: .critical)それぞれ指定する場合
RulesManager( majorUpdateRules: Rules(promptFrequency: .immediately, forAlertType: .force), // A.b.c.d minorUpdateRules: Rules(promptFrequency: .immediately, forAlertType: .optional), // a.B.c.d patchUpdateRules: Rules(promptFrequency: .daily, forAlertType: .skip), // a.b.C.d revisionUpdateRules: Rules(promptFrequency: .weekly, forAlertType: .skip) // a.b.c.D )RuleManagerのコードは以下。
参考資料
強制アップデートで検索すると検索するとここら辺の記事が出てくる
teckmemo : 簡単にアプリのアップデート通知を行う
Sirenを使って iOSアプリに強制アップデート実装するよ
狛ログ : iOSアプリのアップデートをSirenを使って実装する。以下がsirenのソース。これを読んだ方がわかりやすい
- 投稿日:2020-01-18T01:36:40+09:00
iOSアプリ内にAPIアクセスキーを保持するベストプラクティス(Swift)
はじめに
iOSアプリ開発において、APIアクセスキーの管理方法に疑問を持ちました。
iOSアプリ開発で、APIアクセスキーなどの機密情報を管理するベストプラクティスを実は知らない?
— ウホーイ (@the_uhooi) January 11, 2020
privateリポジトリだとソースコードに直書きしてしまいがちなので、ちょっと調べてみようTwitterでいろいろ教えていただき、自分の中でベストプラクティスを考えたので紹介します。
結論
先に結論を記載します。
- CocoaPodsを使っている、かつライブラリの追加に抵抗がない → cocoapods-keysを導入する
- CocoaPodsを使っていない、またはライブラリの追加に抵抗がある
- リポジトリがprivate →
.swift
ファイルへ直接書く- リポジトリがpublic → CI時に
.swift
ファイルへ注入する解説
結論のみではわからないので、解説します。
cocoapods-keys
CocoaPodsのプラグインで、機密情報をキーチェーンアクセスで管理するツールです。
https://github.com/orta/cocoapods-keys私は使ったことがないのですが、 こちらの記事 を読む限り、非常に便利なツールです。
CocoaPodsを使っているなら、導入を検討してもよさそうです。リポジトリがprivate
CocoaPodsを使っていない、またはライブラリの追加に抵抗がある場合は、手動で対応する方法が考えられます。
リポジトリがprivateの場合、
.swift
ファイルへ直接書いて問題ないと思います。
理由は当たり前ですが、privateリポジトリからソースが漏れることは(基本的に)ないためです。AccessTokens.swiftlet fooAccessToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" // 直接書いてOK注意点として、
.plist
ファイルなどのリソースに保持すると、エンドユーザーが読み取れてしまいます 。
.swift
ファイルはコンパイルされますが、リソースはそのまま.ipa
ファイル内に保持されます。
もしリソースで機密情報を管理していたら、すぐに対応すべきです。リポジトリがpublic
APIアクセスキーを使っているOSSなど、リポジトリがpublicな場合も考えられます。
その場合はソースに直接書けないので、CI時に注入します。①ローカルの
.swift
ファイルにアクセスキーを記述するprivateリポジトリと同様、
.swift
ファイルをプロジェクト内に作成してアクセスキーを記述します。AccessTokens.swiftlet fooAccessToken = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"これでローカルでの開発は問題なく行えます。
②アクセスキーを含むファイルをGitの管理外にする
このままリモートリポジトリにプッシュすることはできないので、
.gitignore
に対象ファイルを追記します。.gitignore+ AccessTokens.swift
③プロジェクトファイルのみプッシュする
対象ファイルを追加したプロジェクトファイルのみリモートリポジトリにプッシュします。
④CIサービスにアクセスキーを保持する
ほとんどのCIサービスには機密情報を暗号化して保持する機能があると思うので、活用します。
GitHubの場合、 Secrets という機能があるので、そこでアクセスキーをシークレットとして保持します。⑤CI時にアクセスキーを注入する
保持したアクセスキーをCI時に注入します。
GitHub Actionsの場合、以下のようなステップをビルド前に実行します。main.yml- name: Inject access token run: echo "let fooAccessToken = \"${{ secrets.FOO_ACCESS_TOKEN }}\"" > ./Foo/AccessTokens.swiftこれでCI時にアクセスキーを
.swift
ファイルへ注入できます。⑥Makefileを用意する
自分以外の開発者のために、Makefileを用意すると親切です。
以下に例を記載します。Makefile.PHONY: inject-tokens inject-tokens: echo "let fooAccessToken = \"${FOO_ACCESS_TOKEN}\"" > ./Foo/AccessTokens.swiftコマンドをREADMEに書くことで、他の人もローカルで開発しやすくなります。
README.mdRun `make inject-tokens FOO_ACCESS_TOKEN={Foo Access token}` .
おわりに
これでiOSアプリ開発で安全にAPIアクセスキーを管理できます!
もし他にベストプラクティスを持っている方がいたら、教えていただけると嬉しいです。
参考リンク