20200711のiOSに関する記事は5件です。

メモ:Swift5で初回起動判定

n番煎じのネタだと思いますが、自分用のメモ。

func setup() {
    let visit = UserDefaults.standard.bool(forKey: "visit")
    if visit {
        //二回目以降
        print("二回目以降")
    } else {
        //初回アクセス
        print("初回起動")
    }
}

setup()をAppDelegateとかSceneDelegateに追加するだけです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FlutterにFirebaseのIn-App Messagingを入れるとiOSビルドが失敗する

FlutterアプリにFirebaseのIn-App Messagingを入れようとして、iOSビルドが出来なくてハマったのでその解決方法をメモとして共有します。

環境など

ツールなど バージョンなど
MacBook Air Early2015 macOS Mojave 10.14.6
Android Studio 3.6.1
Java 1.8.0_131
Flutter 1.12.13+hotfix.9
Dart 2.7.2
Xcode 11.3.1

導入手順

In-App Messagingは、基本的にライブラリを導入するだけで、コーディングはする必要が無いものです。(受け取って標準的な表示をするだけなら)

なので、以下だけでやりました。

1.依存関係を追加

Flutter用のパッケージはこちらにあります。
https://pub.dev/packages/firebase_in_app_messaging

pubspec.yaml
  firebase_in_app_messaging: ^0.1.2

pub getして、ビルドしました。

2.キャンペーンを作成

Firebaseの以下のページからキャンペーンを作成します。

inappmessaging.png

「新しいキャンペーンの作成」をクリックすると、以下のような画面になります。

iam_campagin.png

画像が必須なので頑張って何か入れてください。
(横向き用に画像が潰れるのはなんとかならないのか・・・)

ところで、In-App Messagingって、まだベータ版なんですね・・・

Androidは、これで基本的には上手くいきます。
私はService fetch error: PERMISSION_DENIED: Firebase In-App Messaging API has not been usedというエラーが出てしばらく表示されなかったのですが、google-services.jsonをダウンロードし直してきたら直り、無事表示が出来ました。

エラー内容

問題は、iOSで表示しようとビルドしたときです。
以下のようにビルドエラーが出ました。

duplicate symbol '_OBJC_CLASS_$_ "FIRIAMDefaultDisplayImpl'"

どうやら、以下のパッケージで同じクラス定義がありシンボルが重複しているというエラーのようです。

  • FirebaseInAppMessaging
  • FirebaseInAppMessagingDisplay

解決方法

いろいろググって辿り着いたのが、FirebaseのIssuesページです。

https://github.com/FirebaseExtended/flutterfire/issues/2151

こちらにある、FirebaseとIn-App Messagingのバージョンを強制的に指定することで解決しました。
※ダウングレードしていることになるので、他のFirebaseのパッケージが整合性取れなくなる可能性があります。対応にはご注意下さい。

具体的には、以下のバージョンを強制的に指定することにします。

  • Firebase (6.15.0)
  • FirebaseInAppMessaging (0.16.0)

(1)Podfileを編集する

どうするかというと、Podfileファイルを編集します。

# avoiding to duplicate symbol error
pod 'Firebase', '6.15.0'
pod 'FirebaseInAppMessaging', '0.16.0'

(2) Podfile.lockを削除

Podfile.lockはプロジェクトフォルダのiosフォルダ下にあります。

Podfile.png

(3) flutter cleanを実行

$ flutter clean

(4) pod installを実行

$ pod install

(5) Flutterでビルド、実行する

これで無事ビルドが通り、メッセージもちゃんと表示出来ることを確認しました。

2.修正状況

関連の修正PRは出ているようですので、注視しておくと良いかも知れません。

https://github.com/FirebaseExtended/flutterfire/pull/1957
https://github.com/FirebaseExtended/flutterfire/pull/2701

In-App Messagingのススメ

Push通知(Firebase Cloud Messaging)と違って、アプリを起動したときにしか表示してくれませんが、Pushよりずっと楽に導入できるので、アプリのアップデートの案内とか、アップデートした後の新機能の紹介とか、アプリを起動した上でのメッセージ表示で十分な場合は、かなりオススメです。

特にiOSの場合、証明書の更新とかも不要になるので、運用的にかなり助かるのではないでしょうか。

と言うことで、頑張ってPush通知を導入するより、In-App Messaging導入、いかがでしょうか?

今回、In-App Messagingを入れることにしたのは理由があって、アプリの強制アップデートのためにRemote Configを使っているのですが、iOS9.3のiPadで、一度読み込んだらその後値を一切再取得してくれないという不具合に気付き、そこで、iOS10未満の端末向けに、最初はPush通知を入れようかと思ったのですが、証明書やらでハードルが高いので、お手軽そうなIn-App Messagingを試してみた、という次第です。

というか、これで、自前の強制アップデートダイアログの表示も不要になりますね。
ナンテコッタイ\(^o^)/

まあ、まだベータなので・・・というところが、業務で導入するには躊躇うところでしょうか^^;

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

FlutterのiOSアプリで、端末のエッジ部分の onTapDown が遅延する

経緯

とあるアプリの開発で、ユーザのタップ操作に即座に反応する必要があり、画面の左右にボタン領域を用意して、 onTapDown でイベントをハンドリングしようとしました。
iOS simulatorで確認しているところでは上手く動いていたのですが、iPhone XRなどの実機で確認してもらうと、「画面を押した瞬間に反応せず、コンマ数秒経ってから反応しているように見える」という指摘があり、調査しました。

状況としては、以下の動画のようなイメージです。

d0fme-7zyqw.gif

最初の2タップは、比較的中央寄りをタップしているので、指が触れた瞬間ぐらいでテキストの行が増えています。
次の2タップは、意図的に画面端をタップしており、タップした瞬間から500msecぐらい遅れて行が増えています。

調査していくと、iOSのOS側の制御として「エッジに触れられたときには、OSのジェスチャーかもしれないから、アプリにイベントを渡すのは少し待つ」的な動作がありそうでした。

そして、iOSの preferredScreenEdgesDeferringSystemGestures にて [.left, .right] を返せば良さそう、、、という記事も発見したのですが、今回の開発ではFlutterを利用していたため、UIViewControllerが露出しておらず、継承してそれを利用する方法がわかりませんでした。

解決策

調べていくと、Flutterで利用されている UIViewController は、 FlutterViewController ということがわかりました。

また、同僚からのアドバイスで、 extension を使ってみました。

結果としては、 {project dir}/ios/Runner/AppDelegate.swift の末尾に、以下の記述を追加することで改善しました。

public extension FlutterViewController {
    override var preferredScreenEdgesDeferringSystemGestures: UIRectEdge {
        return [.left, .right]
    }
}

改善後の動画です。

59v1n-f7upv.gif

こちらも、上の動画と同様に、最初の2タップは中央寄り、次の2タップは端をタップしていますが、どちらもタップした瞬間に反応しています。

その他

同じように、 preferredScreenEdgesDeferringSystemGestures にて [.bottom] を返すと、1度はホーム画面への遷移を防げます。

5jlyk-lvypl.gif

一般的なアプリで実装されているとただ迷惑ですが、ガチャガチャ操作するようなゲームなどでは、この指定をしても良いかもしれませんね。

その他2

多くのアプリでは、こういった制御が必要になったとしても、特定の画面のみかと思います。
Flutterパッケージを作成し、 preferredScreenEdgesDeferringSystemGestures が返す値を変数化、Flutterアプリ側からの呼び出しでその変数を書き換え、 setNeedsUpdateOfScreenEdgesDeferringSystemGestures を呼び出してやる、、、というのが良さそうではあります。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ViewController を閉じる dismiss

ViewController を dismiss 処理

qiita.rb
    @IBAction func backButton(_ sender: Any) {
        self.dismiss(animated: true, completion: nil)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

iOS端末でWiFi接続パスワードを共有する3つの方法

はじめに

この記事では、macOSおよびiOS端末でWiFiの接続パスワードを共有する方法を紹介します。

このような場合にお役立てください。

  • 職場、学校、家庭などで多くの端末にWiFiパスワードを設定する必要がある
  • WiFi設定を配布するプログラムを製作する

個別の方法を解説する記事はありましたが、方法をまとめて比較している記事がありませんでした。
どの方法がどのような場面に適しているのか、比較検討していただければ幸いです。

想定する環境

この記事は以下の環境を想定しています。

  • iOS 13.5
  • macOS 10.15

記事を読む前に、お手元の環境をご確認ください。

方法1 : iCloudキーチェーン

同一のAppleIDでサインインしている端末同士なら、iCloudキーチェーンで接続パスワードを共有できます。

Apple - iCloud キーチェーンを設定する

iCloud キーチェーンには、クレジットカード番号と有効期限日 (セキュリティコードの保存や自動入力はされません)、パスワードとユーザ名、Wi-Fiのパスワード、インターネットアカウントなどが保存されます。

使いどころ

自分自身が所有する複数の端末で、接続パスワードを共有および更新するのに適しています。

共有の手順

iCloudキーチェーンで接続パスワードを共有している場合、WiFiアクセスポイントに接続するだけでパスワードが自動入力されます。特別な手順は必要ありません。

注意点

iOSの設定からネットワーク設定を削除すると、iCloudキーチェーン上の接続パスワードも同時に削除されます。パスワードを共有している端末で再設定が必要になるのでお気をつけください。

方法2 : Bluetooth

一定の条件を満たしたiOS端末同士なら、Bluetoothで接続パスワードを共有できます。

Apple - iPhone、iPad、iPod touchでWi-Fiのパスワードを共有する方法

使いどころ

家族、友人、職場などで限定した相手に接続パスワードを共有、配布するのに適しています。

準備

パスワードを送信する端末を端末A、受信する端末を端末Bと呼びます。それぞれの端末で以下の準備が必要です。

端末ABで共通

  • AppleIDにサインインしている(インターネットはオフラインでもOK)
  • WiFiがONになっている
  • BluetoothがONになっている
  • インターネット共有がOFFになっている
  • 連絡先アプリに相手のAppleIDと紐付けられたメールアドレスが登録されている

端末A

  • 画面ロックが解除されている
  • 共有したいWiFiアクセスポイントに接続している

端末B

  • 端末AのBluetoothが届く範囲にいる

共有の手順

端末Bで共有したいWiFiアクセスポイントに接続します。すると端末Aに以下のダイアログが表示されます。

画像出典 - Apple

端末Aのダイアログで許可をすると、端末Bにパスワードが共有されます。

方法3 : QR Wi-Fi

QRコードでもWiFiのSSIDとパスワードが共有できます。

QR Code Recognition on iOS 11

こちらの動画の3:30から、QR Wi-Fiが触れられています。

使いどころ

OSの異なるスマホ同士で接続パスワードを共有するのに適しています。また、イベント会場など一時的に不特定多数の人に接続パスワードを配布するのにも適しています。

準備

まず、以下の構文にしたがって文字列を作ります。

WIFI:S:【SSID名】;T:【WEP or WPA】;P:【パスワード】;;

SPはSSID名と接続パスワードです。TはWiFiの暗号化方式を指定します。最近のWiFiアクセスポイントはほぼWPAを使用しています。S,T,Pの順番は入れ替えても動作します。

たとえばSSIDがTEST-A-789、パスワードがwifi-passwordの場合

WIFI:S:TEST-A-789;T:WPA;P:wifi-password;;

となります。

次に、この文字列をQRコード化します。QRコードは以下の方法で生成できます。

iPhoneで書いた住所やURLなどの短い文章・文字列はQRコード化して他のスマホへ

この記事では、ダイアログで入力された文字列をQRコード化しています。
ショートカットを変更して、入力元をクリップボードにするのもオススメです。

共有の手順

iOS端末のカメラを起動し、このQRコードを読み取ると通知がポップアップします。この通知をタップすれば、端末がWiFiアクセスポイントに接続されます。

また、このQRコードはAndroid端末でも読み込めます。

注意点

WebサービスでQRコードを生成すると、サービスのオーナーに接続パスワードが暗号化されない状態で渡ります。接続パスワードを含んだQRコードはネットワークを介さず、端末内で生成することをオススメします。

QRコードには接続パスワードが平文で格納されています。そのため撮影した写真からも簡単にパスワードが復号できます。イベントなどで不特定多数がQRコードを撮影した後は、接続パスワードを変更しましょう。

参考記事

iPhone で QR コードからの Wi-Fi 接続が意外と知られていなかったので補足
QRコードでお手軽設定

以上、ありがとうございました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む