1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JSONで受け取った数値のフィルタリング(NSPredicate)でハマった話

Last updated at Posted at 2017-12-30

やりたかったこと

ある関数にいくつかidのセット(id1,id2)を渡す。渡したもののうち、
下記のNSDictionayの配列に含まれる要素に一致したものを取り出したい。

  • フィルタ用のデータ構造

これはAPIからJSONで取得され、NSDictionaryのNSArrayで格納している。

   (
    {
        id1 = 4744139161607189037;
        id2 = 288;
    },
        {
        id1 = 4744139163368868020;
        id2 = 288;
    }
   )
  • サンプル関数 ※上記のNSArrayはdataという変数で表現
.objc
+(BOOL) sampleFunc:(NSString*) id1 id2:(NSString*) id2 {
    NSString *query = [NSString stringWithFormat:@"id1 == %@ && id2 == %@", id1, id2]; //クエリ作成
    NSPredicate *predicate = [NSPredicate predicateWithFormat:query]; //クエリをNSPredicateにする
    NSArray *matched = [data filteredArrayUsingPredicate:predicate]; //predicateでフィルタリング
    NSLog(@"%@",matched);
}

ハマり具合

  • 実際に関数に渡していた引数のリスト(処理的には、リスト分だけ関数を呼んでいる)
4744139161607189037, 288
4744139163368868024, 288
4744139163368868020, 288

このとき、一致しないはずの4744139163368868024,288が一致扱いになっていた。

ここでデバッガでpo dataとかしてdataの中身を確認してみると..


(
        {
        id1 = "4.74413916160719e+18";
        id2 = 288;
    },
        {
        id1 = "4.744139163368868e+18";
        id2 = 288;
    }
)

あっ!丸められている!!
それで47441391633688680244744139163368868020
同じ数字扱いになっていたのですね。

JSONで受け取っている関係で、2^53-1(2の53乗-1)以上の数字は丸められてしまいます。
なので、API側でid1の方は文字列として返さないといけないようです。これで勝てる!!

・・・

大丈夫じゃなかった。こんどは何も一致しない。

またAPIから受け取ったフィルタ用データを見てみる。

(
        {
        id1 = 4744139161607189037;
        id2 = 288;
    },
        {
        id1 = 4744139163368868020;
        id2 = 288;
    }
)

ちゃんと文字列になっている。じゃあフィルタ条件がおかしい?

.objc
+(BOOL) sampleFunc:(NSString*) id1 id2:(NSString*) id2 {
    NSString *query = [NSString stringWithFormat:@"id1 == %@ && id2 == %@", id1, id2];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:query];
    NSArray *matched = [data filteredArrayUsingPredicate:predicate]; //dataは上記のNSArray
    NSLog(@"%@",matched);
}

うーむ。。あっ!

文字列にしたんだからこうじゃなくて

NSString *query = [NSString stringWithFormat:@"id1 == %@ && id2 == %@", id1, id2];

こうですね

NSString *query = [NSString stringWithFormat:@"id1 like \"%@\" && id2 == %@", id1, id2];

ちなみに比較演算子をlikeにしただけだと
'Can't create a regex expression from object 〜.'
とかいわれて怒られるので、プレースホルダ前後のダブルクォートは必須です。(これ気付くのも時間かかったorz)

おつかれさまでした

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?