LoginSignup
1
0

More than 1 year has passed since last update.

Flutter for Webのデバッグとビルド環境で変数の型が違う件

Posted at

プッシュ通知の送信履歴の表示について · Issue #1307 · NIFCLOUD-mbaas/UserCommunity、こちらの件で調査してはじめて知ったのですが、Flutter for Webで型判別をしていると微妙にハマります。

前提条件

ニフクラ mobile backendのデータストア(クラウドデータベース)では、文字列や数字、真偽値、配列、オブジェクトなど様々な形式を扱います。かつNoSQL型データベースなのでフィールド名も自由に付けられます。そのため、型指定する言語とは相性があまり良くなかったりします。

特にオブジェクトでデータが入っている中でも、ニフクラ mobile backendでは以下の型が特殊になります。

  • 日時型
    {__type: "Date", iso: "日付文字列"} という形でデータが入っている
  • 位置情報型
    {__type: "GeoPoint", latitude: 緯度の数値, longitude: 経度の数値} という形でデータが入っている
  • リレーションデータ
    {__type: "Pointer", className: "対象クラス名", objectId: "対象データのキー"} という形でデータが入っている

このあたりを判別するために、入っているデータの型を調べる必要がありました。

やっていたこと

最初のコードです。

// データの型を調べる
if (value.runtimeType.toString() == '_JsonMap' ||
        value.runtimeType.toString() ==
            '_InternalLinkedHashMap<String, dynamic>') {
	var map = value as Map;
	if (map['className'] != null) {
		// リレーションデータ
	}
	if (map.containsKey('__type') && map['__type'] == 'GeoPoint') {
		// 位置情報型
	}
	if (map.containsKey('__type') && map['__type'] == 'Date') {
		// 日時型
  }
} else {
	// それ以外
}

value.runtimeType.toString() の値ですが、デバッグ環境では以下のようになります。 _InternalLinkedHashMap<String, dynamic> になるのはスマホの場合だった覚えがあります。

userSettingValue is _JsonMap
deliveryExpirationTime is String
deliveryNumber is int
action is String
badgeIncrementFlag is bool
error is _JsonMap
target is List<dynamic>

ビルド環境での実行

いわゆる flutter build web をやって生成されたコードでの実行結果です。 minified:F5 とか minified:bR といった謎の文字列が入ってきます。この結果として、if文がうまく動かずに不具合が起きていました。

createDate is minified:bR
updateDate is minified:bR
acl is minified:n1
dialog is bool
error is minified:F5
objectId is String
deliveryTime is minified:F5
target is minified:r<dynamic>

修正後

あまり良くはないのですが、Mapとして評価してエラーになるかどうかで判別することにしました。

try {
	var map = value as Map;
	if (map['className'] != null) {
		// リレーションデータ
	}
	if (map.containsKey('__type') && map['__type'] == 'GeoPoint') {
		// 位置情報型
	}
	if (map.containsKey('__type') && map['__type'] == 'Date') {
		// 日時型
	}
	_fields[name] = value;
} catch (e) {
	_fields[name] = value;
}

is で判別できそうな気もするのですが、過去にうまくいかなかった覚えがあるんですよね…(そのために runtimeType.toString() を使っている覚えが)。ビルド環境によって変数の型が異なるのも面倒なので、今回のやり方の方がシンプルかなと思っています。

他に良い方法があれば、ぜひコメントで教えてください!

NCMBのDart/Flutterパッケージはncmb | Dart Packageにて公開しています。ぜひ試してみてください!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0