6

私はプッシュ通知を使用し、他の人と同じようにデバイストークンを保存します。まず、それらをアプリの文字列に変換します。

NSString *deviceTokenString = [[[token description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]
                               stringByReplacingOccurrencesOfString:@" " withString:@""];

次に、それらをサーバーに配置します。ここで、ActiveRecordはそれらをcharacter varying(255)列に格納します。

Device.where(:token => device_token, :username => username).first_or_create!(:model => model)

2つのトークンが同じでないことを確認する検証があります。これは、常に当てはまるはずです。

class Device < ActiveRecord::Base
  belongs_to :user
  validates_uniqueness_of :token
end

ただし、トークンの一意性の検証エラーが発生し始めました。

ActiveRecord::RecordInvalid: Validation failed: Token has already been taken

psqlの手動クエリは、デバイスが別のユーザーの下ですでにテーブルにあるトークンに登録しようとしていることを確認します。これは不可能ではないでしょうか?トークンを切り捨てて変換する方法に何か問題がありますか?問題が最初に発生したときに見つけたすべてのコード例を確認しましたが、誰もが最初のコードサンプルにリストした方法を使用しているようです。

4

3 に答える 3

7

誰かがログアウトしてから別のアカウントでログインした場合、デバイスが別のユーザーの下ですでにテーブルにあるトークンに登録しようとすることがあります。

サーバー上でユーザーuserとトークン文字列に対して次のことを行いますtoken(一度に1つのデバイスにログインできるのは1人のユーザーのみであると想定しています)。

  1. Deviceforがあるかどうかを確認しtoken_stringます。
  2. デバイスがない場合は、とのデバイスを作成しtoken_stringますuser
  3. デバイスがあり、そのユーザーがいない場合はuser、そのユーザーをに更新しますuser

そうすれば、プッシュ通知はデバイスに最後にログインしたユーザーに送信されます。

デバイスでを16進文字列に変換する方法に関しては、NSDataに依存しないでください-[NSData description]。プログラムで行う方がよい(入力され、テストされていない):

- (NSString *)hexStringForData:(NSData *)data
{
    NSUInteger length = data.length;
    const char *bytes = data.bytes;
    NSMutableString *result = [NSMutableString stringWithCapacity:length * 2];
    for (int i = 0; i < length; i++) {
        [result appendFormat:@"%02x", bytes[i] & 0xff];
    }
    return [result copy];
}
于 2013-03-07T11:22:21.923 に答える
1

私はこれを推測しますが、それが何のためにあるのか、推測してください。

iOSデバイスがバックアップから復元されたとき、または誰かがiPhone4からiPhone5にアップグレードしたとき、または誰かがiPhoneを妻に渡したり、eBayで販売したりすると、複製されます。 /冗長/紛らわしいデバイスデータ。私は間違いなくそれが起こるのを見てきましたが、特にAPNSトークンではそうではありません。

これがAPNSドキュメントがそれについて言わなければならないことです:

アプリケーションが起動するたびにデバイストークンを要求してプロバイダーに渡すことで、プロバイダーがデバイスの現在のトークンを持っていることを確認できます。ユーザーがバックアップを作成したデバイスまたはコンピューター以外のデバイスまたはコンピューターにバックアップを復元する場合(たとえば、ユーザーがデータを新しいデバイスまたはコンピューターに移行する場合)、ユーザーはアプリケーションを少なくとも1回起動する必要があります。通知を再度受信します。ユーザーがバックアップデータを新しいデバイスまたはコンピューターに復元するか、オペレーティングシステムを再インストールすると、デバイストークンが変更されます。さらに、デバイストークンをキャッシュして、プロバイダーに渡さないでください。必要なときはいつでもシステムからトークンを取得してください。アプリケーションが以前に登録されている場合は、registerForRemoteNotificationTypesを呼び出します。

したがって、私はあなたのコードを見ていませんが、あなたの「重複した」トークンは、毎回登録しないこと、ある種のキャッシュ、およびデバイスの復元の何らかの組み合わせに関係しているようです。

于 2013-03-06T13:08:41.623 に答える
0

デバイスが登録されたときに何が起こるかを理解することが重要です。サーバーに次のPOSTを送信します。

/passkit/v1/devices/<deviceID>/registrations/<typeID>/<serial#>

そして、JSONペイロード内には。がありpush_tokenます。deviceID重要なのはとの両方push_tokenです。Appleに関する限り、Appleのシステムを介してデバイスと通信しpush_tokenます。

についてdeviceIDは、実際に使用される物理デバイスです。push_tokenデバイスが複数回登録する可能性があるという事実は関係ありません。コードは、最新の登録試行に基づいてDB内のを更新する必要があります。それについてです。

于 2013-03-09T09:50:11.593 に答える