ノート的なやつ

学んだことの備忘録です。ご指摘等お待ちしております。

Firebase+Vue.js+Nuxt.jsでauth周りのエラー

久々にローカルマシンでvueプロジェクトを立ち上げたら_plugins_firebase__WEBPACK_IMPORTED_MODULE_6__.default.auth is not a function An error occurred while rendering the page. Check developer tools console for details. のエラーが出た

以下の対処を行って解決した firebaseをimportしている箇所の下でrequire('firebase/auth') stackoverflow.com

RxSwift(MVVM)でのインディケーター表示状態の管理

自分は普段こうやっています的な紹介と悩み

インディケーターの状態管理について、自分はいつも以下のような形で管理しています。

enum LoadingStatus {
  case none
  case loading
  case dismiss
}

class XViewModel {
  
  private let disposeBag = DisposeBag()
  let loadingStatus: BehaviorRelay<LoadingStatus> = BehaviorRelay(value: .none)
  let isSuccess: PublishRelay<Bool> = PublishRelay()
  
  func fetchData() {
    AnySession
      .subscribe(onNext: { [weak self] _ in
        guard let self = self else { return }
        self.loadingStatus.accept(.dismiss)
      }, onError: { [weak self] _ in 
        self.loadingStatus.accept(.dismiss)
      })
      .disposed(by: disposeBag)
  }
}

class XViewController: UIViewController {
  
  let viewModel = XViewModel()
  private let disposeBag = DisposeBag()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    setupObserver()
    
    viewModel.fetchData()
  }
  
  func setupObserver() {
    viewModel.loadingStatus
      .subscribe(onNext: { status in
        switch status {
        case .none:
          break
        case .loading:
          // インディケーターを出す処理
        case .dismiss:
          // インディケーターを消す処理
        }
      })
      .disposed(by: disposeBag)
  }
}

これ自体はHUDの表示非表示の状態管理が割と綺麗な形でできていると思います(個人的には)。 ただ、これだとエラーの時に数秒だけ表示させるエラー表示のインディケーター(HUD?)の管理が同時にできないので悩んでいます。 LoadingStatusを

enum LoadingStatus {
  case none
  case loading
  case error(message: String)
  case dismiss
}

みたいな形にすることも検討したのですが、運用する時に

// ViewModel
func fetchData() {
    AnySession
      .subscribe(onNext: { [weak self] _ in
        guard let self = self else { return }
        self.loadingStatus.accept(.dismiss)
      }, onError: { [weak self] _ in 
        self.loadingStatus.accept(.error(message: "エラーが発生しました"))
      })
      .disposed(by: disposeBag)
  }
  
// ViewController
func setupObserver() {
    viewModel.loadingStatus
      .subscribe(onNext: { [weak self] status in
        guard let self = self else { return }
        switch status {
        case .none:
          break
        case .loading:
          // インディケーターを出す処理
        case .error(message):
          // エラーのインディケーターを出す処理
          // 何らかの時間を待つ処理 ←ここが綺麗じゃない
          self.viewModel.loadingStatus.accept(.dismiss) // ←ここが綺麗じゃない
        case .dismiss:
          // インディケーターを消す処理
        }
      })
      .disposed(by: disposeBag)
}

のような形になってしまい、あまり綺麗な形で運用できていないので、何かアドバイス等あれば教えてください。 本当は↓こうしたい

AnySession
      .subscribe(onNext: { [weak self] _ in
        guard let self = self else { return }
        self.loadingStatus.accept(.dismiss)
      }, onError: { [weak self] _ in 
        self.loadingStatus.accept(.error(message: "エラーが発生しました"))
      }) // onErrorの場合だけ数秒待って self.loadingStatus.accept(.dismiss)をしたい
      .disposed(by: disposeBag)

オレオレマークダウンチートシート

基本的な表

|左寄せの列|中央寄せの列|右寄せの列|
| :--- | :---: | ---:|
|val01|val02|val03|
|val11|val12|val13|
左寄せの列 中央寄せの列 右寄せの列
val01 val02 val03
val11 val12 val13

セルの中ではいろんなことができるよ

|col1|col2|col3|
|-----|-----|-----|
|*斜線*|~~打ち消し~~|**強調**|
|改行も<br>できる|[リンクも貼れる](http://onanchara.hatenablog.jp/)|aaa|
col1 col2 col3
斜線 打ち消し 強調
改行も
できる
リンクも貼れる aaa

アプリ内課金検証方法

会社でアプリ内課金を実装し直した経緯があり、一人で検証していたのですが、色々とハマったのでここに備忘録として残しておきます。

アプリ内課金検証方法手順

Sandboxユーザーを作成する

  • Sandbox用メールアカウントを用意 ※1
  • iTunesConnect Sandboxテスターにメールアドレスを登録
  • 登録したメールアドレスにAppleDeveloperからのメールアドレスが届くので承認。

※1 今まで一度もAppStoreなどで実際の課金履歴が無いメールアドレスに限る

アプリの準備

  • 実機にアプリをインストール(使用するビルドはXcode、Testflightどちらでも可)
  • 実機に紐づいているAppleアカウントから一旦サインアウトする * 大事。やらないとSandbox環境でのテストができません。

アプリ課金検証

  • 課金決済時にEnvironment: sandboxになっている※1ことを確認する(画像参照※2)
  • 課金決済時にAppleIDでのログインを求められるので※1上記で登録したSandboxユーザーのアカウントを入力する
  • 購入を押下

※1 アプリではなく公式課金APIのStoreKitの仕様

注意点

Sandbox環境下での購読期間

Sandbox環境下では時間の流れが変わる

設定した購読期間 Sandbox環境下での時間
7日 3分
1ヶ月 5分
2ヶ月 10分
3ヶ月 15分
6ヶ月 30分
1年 1時間

※Sandbox環境下での自動更新は6回まで自動で行われる。また、キャンセル等はできない仕様になっている。つまり、一ヶ月プランを購読処理した場合は30分(5分 × 6回)間自動更新される

"iTunes Storeに接続できません"エラーケースまとめ

このエラーは様々な要因によって引き起こされる模様。遭遇したケースをまとめていきます。 Sandbox環境は不安定なので結構検証大変だったりするみたいです。頑張って!

そもそもStoreKit周りのコードが間違っている

Sandboxユーザーで検証できていない

  • 課金処理をテストする前にAppleStoreからサインアウトしていない
  • SandboxアカウントがAppleStoreでの使用などにより無効化されている などが考えられる。後者ならSandboxユーザーを再作成することで対応できると思われる。

Sandboxサーバーが落ちている

下記URLを確認 https://developer.apple.com/system-status/

短時間に複数回リクエストを送る

そういうエラーメッセージ返して欲しいですよね、わかります

参考URL

公式: Sandboxユーザーの作成方法
公式: 推奨されるアプリ内課金のテスト方法

以下その他参考記事 https://ameblo.jp/principia-ca/entry-12071724382.html https://www.aguuu.com/archives/2012/12/in-app-purchase-annotation/

Git Subtreeがよくわからなかったので練習した

Git Subtreeに関してやったこと/わかったこと(正しいかは不明)

準備
メインのレポジトリのブランチ
-master
-test-branch

Subtreeに分割する流れ

Subtreeにしたいファイルを分割(Subtreeにしたいファイルのコミットだけが分離されたブランチができる) git subtree split --prefix=practice-subtree-main-project/willBeSubtree -b make-subtree-branch

そのブランチに移動 git checkout make-subtree-branch

Subtreeのレポジトリをリモートに登録 git remote add subrepo git@github.com:hogehoge/practice-subtree-subtree-project.git

Subtreeのレポジトリにpush git push subrepo make-subtree-branch

(この後元のブランチに戻れなくてあたふたした)
git clean -f とか git checkout "エラーが出たファイル" とかやってどうにか戻れた

Subtreeのレポジトリの内容を更新

前提: メインのレポジトリにいる状態
① サブツリーにしているファイルを更新 git add "更新対象"

② 普通にコミット git commit -m "かめはめ波プロパティ追加"

③ 変更をサブツリーにプッシュ git subtree push --prefix=practice-subtree-main-project/willBeSubtree subrepo make-subtree-branch

④ 変更をメインにプッシュ git push origin test-branch

間違ってたらコメントください。(多分間違っているので.....)

Swift 4.1 分割キーボード判定その2

1 => Swift4 分割キーボード判定 - ノート的なやつ

分割キーボードについて、最新付近の情報がなかったので、主要ないくつかの通知について表にまとめました。

×->通知が飛ばない ○->番号の順に通知が飛ぶ

  • Dock(通常)キーボード
通知\状態 出す しまう -> Split -> UnDock 回転
WillShow × × ×
WillHide ×
WillChangeFrame ①③
  • Split(分割)キーボード
通知\状態 出す しまう -> Dock -> UnDock 回転
WillShow × × × ×
WillHide × × × × ×
WillChangeFrame
  • UnDockキーボード
通知\状態 出す しまう -> Dock -> Split 回転
WillShow × × × ×
WillHide × × × × ×
WillChangeFrame

参考
https://qiita.com/reikubonaga/items/5df48be2d65838444373

Swift4 分割キーボード判定

分割キーボードが出たり入ったりした時の判定を調べていて、Notificationで飛ぶ通知次第で処理を簡単に分けれるでしょと思ってたらそうでもなかったのでメモ。

分割キーボードが出たり消えたりした時の通知はUIKeyboardWillChangeFrameNotificationないしは UIKeyboardDidChangeFrameNotificationに飛びます。しかし通常のキーボードが出た時も同じ通知が飛んでしまうので、通知を飛ばした先でキーボードの状況によって処理を分けなければいけないみたいですね。

その中で、userInfoで取得できる値には以下のようなものがありました。値はとりあえず適当

  • 分割キーボード出現時
[AnyHashable("UIKeyboardCenterBeginUserInfoKey"): NSPoint: {384, 1159.5},
AnyHashable("UIKeyboardIsLocalUserInfoKey"): 1,
AnyHashable("UIKeyboardCenterEndUserInfoKey"): NSPoint: {384, 588.5},
AnyHashable("UIKeyboardBoundsUserInfoKey"): NSRect: {{0, 0}, {768, 271}},
AnyHashable("UIKeyboardFrameEndUserInfoKey"): NSRect: {{0, 453}, {768, 271}},
AnyHashable("UIKeyboardAnimationCurveUserInfoKey"): 7,
AnyHashable("UIKeyboardFrameBeginUserInfoKey"): NSRect: {{0, 1024}, {768, 271}},
AnyHashable("UIKeyboardAnimationDurationUserInfoKey"): 0.25]
  • 標準キーボード出現時
[AnyHashable("UIKeyboardCenterBeginUserInfoKey"): NSPoint: {384, 1180.5},
AnyHashable("UIKeyboardIsLocalUserInfoKey"): 1,
AnyHashable("UIKeyboardCenterEndUserInfoKey"): NSPoint: {384, 867.5},
AnyHashable("UIKeyboardBoundsUserInfoKey"): NSRect: {{0, 0}, {768, 313}},
AnyHashable("UIKeyboardFrameEndUserInfoKey"): NSRect: {{0, 711}, {768, 313}},
AnyHashable("UIKeyboardAnimationCurveUserInfoKey"): 7,
AnyHashable("UIKeyboardFrameBeginUserInfoKey"): NSRect: {{0, 1024}, {768, 313}},
AnyHashable("UIKeyboardAnimationDurationUserInfoKey"): 0.25]

値を見ると、userInfo["UIKeyboardCenterEndUserInfoKey"]のy値で値で場合分けすればいいように思いますが、duprecated...
なので、userInfo["UIKeyboardFrameEndUserInfoKey"]の微妙な高さの違いで判別するしかないのかなあ。

自分は今回、基準となる入力フォームに対してキーボードが重なっているかどうか程度の判別で良かったので、キーボードのフレームとフォームのフレームの大小で判定しました。