デバイスからユーザーの名前を取得するより良い方法は?

私はデバイス名からユーザー名を抽出する関数を作った。

このアイデアは、初めてアプリを起動したときに、設定ステップをスキップしてユーザーがプレーすることを可能にすることです。

This is a sub-optimal approach, as I can never trust the device name to hold the name of the user. The question is: What is a better way to do this?

下の私の機能は、正しい名前を取得...

  • ... if the default name of the device has not changed ("Sanna's iPod")
  • ... in English,
  • ... in French and similar ("iPod de Sanna")
  • ... in Swedish and similar ("Sannas iPod") if the name does not end with S ("Johannes iPod" => returns "Johanne" but should rather return "Johannes" to be correct, as the name itself ends with an S.)

ユーザーがデバイスの名前を既定のフォーム以外の名前に変更した場合、明らかに名前が正しく取得されません。

- (NSString *) extractPlayerNameFromDeviceName: (NSString *) deviceName  {

   //get words in device name
    NSArray *words = [deviceName componentsSeparatedByString:@" "];
    NSMutableArray *substrings = [[NSMutableArray alloc] init]; 
    for (NSString *word in words) {
        NSArray *subwords = [word componentsSeparatedByString:@"'"];
        [substrings addObjectsFromArray:subwords];
    }

   //find the name part of the device name
    NSString *playerName = [NSString stringWithString: @""];
    for (NSString *word in substrings) {
        if ([word compare:@"iPhone"] != 0
            && [word compare:@"iPod"] != 0
            && [word compare:@"iPad"] != 0
            && [word length] > 2) {
            playerName = word;
        }
    }

   //remove genitive
    unichar lastChar = [playerName characterAtIndex:[playerName length] - 1];
    if (lastChar == 's') {
        playerName = [playerName substringToIndex:[playerName length] - 1];
    }
    lastChar = [playerName characterAtIndex:[playerName length] - 1];
    if (lastChar == '\'') {
        playerName = [playerName substringToIndex:[playerName length] - 1];
    }
    return playerName;
}

私は私のアプリでユーザー名を提案するためにそれを使用します。このようにして、ほとんどのユーザーはユーザー名の書き込みを気にする必要はありません。

私のアプリはiTunesやFacebookのような他のサービスには接続されていませんが、すべてのユーザーはユーザー名が必要です。だから私はどのように名前を取得するのですか?

13
現在のほとんどのデバイスはFBアカウントにリンクされています。その情報を引き出すプロセスは何ですか? (そして、これをセカンダリメソッドフェールセーフとして使用する)
追加された 著者 Albert Renshaw,
@HenriNormak:いいえ、これはiPhone/iPod用のアプリです。基本的にはどこにも接続していないはずです。
追加された 著者 JOG,
@ NathanBaggs:それは私のパラメータを自分の関数に送信されるデバイス名を私に与えます。
追加された 著者 JOG,
私が理解しているように、iOSアプリはFacebookのような他のアプリからは情報を得ることができません。それがあなたが探しているものなら、FacebookのiOS SDKをご覧ください: developers.facebook.com/docs/ios 私の場合は、ユーザーに自分のFacebookに自分の名前にアクセスするように私のアプリに許可するよう頼むことはありません。それは水の橋を渡るようなものです。
追加された 著者 JOG,
サービスはアプリケーションの外部で使用できますか?例えばPC上ではどういう意味ですか?
追加された 著者 Henri Normak,
[[UIDevice currentDevice] name] はあなたが望むものを返しますか?
追加された 著者 Nathan Baggs,

5 答え

私はリッキー・ヘレゲッソンの答えを改善したいと思います。それには以下の特徴があります。

  • 正規表現を使用しているため効率は低下しますが、少し小さくなりますが、一度呼び出す必要があると思います。
  • 「iPod」、「iPhone」、「iPad」の他に、「電話」も含めて使いました。
  • 「iPad」、「iPhone」などの直前にある文字列の最後にのみ「s」を削除します。
  • 「iPad Simulator」のように、最初の単語であるときに「iPad」などを削除します。
  • 各単語の最初の文字を大文字にします。
  • 大文字と小文字を区別しません。
  • 依存関係がないため、関数です。

ここにコードです:

NSArray * nameFromDeviceName(NSString * deviceName)
{
    NSError * error;
    static NSString * expression = (@"^(?:iPhone|phone|iPad|iPod)\\s+(?:de\\s+)?|"
                                    "(\\S+?)(?:['’]?s)?(?:\\s+(?:iPhone|phone|iPad|iPod))?$|"
                                    "(\\S+?)(?:['’]?的)?(?:\\s*(?:iPhone|phone|iPad|iPod))?$|"
                                    "(\\S+)\\s+");
    static NSRange RangeNotFound = (NSRange){.location=NSNotFound, .length=0};
    NSRegularExpression * regex = [NSRegularExpression regularExpressionWithPattern:expression
                                                                            options:(NSRegularExpressionCaseInsensitive)
                                                                              error:&error];
    NSMutableArray * name = [NSMutableArray new];
    for (NSTextCheckingResult * result in [regex matchesInString:deviceName
                                                         options:0
                                                           range:NSMakeRange(0, deviceName.length)]) {
        for (int i = 1; i < result.numberOfRanges; i++) {
            if (! NSEqualRanges([result rangeAtIndex:i], RangeNotFound)) {
                [name addObject:[deviceName substringWithRange:[result rangeAtIndex:i]].capitalizedString];
            }
        }
    }
    return name;
}

これを使用して名前を返します。

NSString* name = [nameFromDeviceName(UIDevice.currentDevice.name) componentsJoinedByString:@" "];

これはやや複雑なので説明します。

  1. The regular expression holds three parts;
    1. At the start of the string, match but do not return "iPhone", "iPod", "iPad" or "phone" and an optional word "de".
    2. At the end of the string, match and return a word that is followed by and optional " 's" (which is not returned) and then "iPad", "iPhone", "iPod" or "phone" (which are not returned either).
    3. This match is the same as the previous, but it should work for Chinese device names. (Adapted from Travis Worm's submission. Please tell me if its wrong.)
    4. Match and return any word that doesn't match the previous rules.
  2. Iterate through all the matches, capitalise them and add them to the array.
  3. Return the array.

名前が「iPad」の前にアポストロフィが付いていない「s」で終わると、「s」が名前の一部であるか複数形であるかを判断する完全な方法がないので、変更しようとしません。名前。

楽しい!

8
追加された

ここでは、すべての名前を取得する代替です。また、 "de"や "s"を使用する言語の最後には 's'は削除されません。また、各名前の最初の文字を大文字にします。

メソッドの実装:

- (NSArray*) newNamesFromDeviceName: (NSString *) deviceName
{
    NSCharacterSet* characterSet = [NSCharacterSet characterSetWithCharactersInString:@" '’\\"];
    NSArray* words = [deviceName componentsSeparatedByCharactersInSet:characterSet];
    NSMutableArray* names = [[NSMutableArray alloc] init];

    bool foundShortWord = false;
    for (NSString *word in words)
    {
        if ([word length] <= 2)
            foundShortWord = true;
        if ([word compare:@"iPhone"] != 0 && [word compare:@"iPod"] != 0 && [word compare:@"iPad"] != 0 && [word length] > 2)
        {
            word = [word stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[word substringToIndex:1] uppercaseString]];
            [names addObject:word];
        }
    }
    if (!foundShortWord && [names count] > 1)
    {
        int lastNameIndex = [names count] - 1;
        NSString* name = [names objectAtIndex:lastNameIndex];
        unichar lastChar = [name characterAtIndex:[name length] - 1];
        if (lastChar == 's')
        {
            [names replaceObjectAtIndex:lastNameIndex withObject:[name substringToIndex:[name length] - 1]];
        }
    }
    return names;
}

使用法:

// Add default values for first name and last name
NSString* deviceName = [[UIDevice currentDevice] name];
NSArray* names = [self newNamesFromDeviceName:deviceName];
// This example sets the first and second names as the text property for some text boxes.
[self.txtFirstName setText:[names objectAtIndex:0]];
[self.txtLastName setText:[names objectAtIndex:1]];
[names release];
4
追加された
私はこのメソッドがうまくいくと信じて、ただ一つの名前を返します。 lastNameが存在するかどうかをチェックしないので、私の例の "Usage"部分が爆発するでしょう。
追加された 著者 Ricky Helgesson,
ありがとう、私はコードを更新しました。
追加された 著者 Ricky Helgesson,
これは「Sannas iPod」ではうまくいかないでしょうか?
追加された 著者 JOG,
ARCと連携するようにこれを更新できますか?
追加された 著者 jesses.co.tt,
私はこの文字列をNSCharacterSetに使用しました:@ "" '\\ "。これはAppleがデバイス名で使用するカーブしたUTF8アポストロフィを含みます。
追加された 著者 Mark Erdmann,
@ jesses.co.tt - リリースを省略して、警告/エラーに従ってください。私はちょうどそれをやった、私は変更しなければならなかった1つだけあったと思う。 NSString * word2 = [word stringByReplacingCharactersInRange:NSMakeRange(0,1)withString:[[word substringToIndex:1] uppercaseString]];ループ変数を再割り当てするのではなく、新しいNSString * word2を作成しました。
追加された 著者 Barrett Clark,

元の Owen Godfrey の回答をSwiftに変換し、Regexprを更新して User's iPhone 6S iPhone 5 de User のようなパターンをサポートしました。 。

I've created a Gist here: https://gist.github.com/iGranDav/8a507eb9314391338507

extension UIDevice {

func username() -> String {

    let deviceName = self.name
    let expression = "^(?:iPhone|phone|iPad|iPod)\\s+(?:de\\s+)?(?:[1-9]?S?\\s+)?|(\\S+?)(?:['']?s)?(?:\\s+(?:iPhone|phone|iPad|iPod)\\s+(?:[1-9]?S?\\s+)?)?$|(\\S+?)(?:['']?的)?(?:\\s*(?:iPhone|phone|iPad|iPod))?$|(\\S+)\\s+"

    var username = deviceName

    do {
        let regex = try NSRegularExpression(pattern: expression, options: .CaseInsensitive)
        let matches = regex.matchesInString(deviceName as String,
                                            options: NSMatchingOptions.init(rawValue: 0),
                                            range: NSMakeRange(0, deviceName.characters.count))
        let rangeNotFound = NSMakeRange(NSNotFound, 0)

        var nameParts = [String]()
        for result in matches {
            for i in 1.. 0 {
            username = nameParts.joinWithSeparator(" ")
        }
    }
    catch { NSLog("[Error] While searching for username from device name") }

    return username
}
}
3
追加された

それがiPodやiPhoneのためのものであれば、なぜユーザー名を使用するのでしょうか? Webサービス用のデバイスを特定する必要がある場合は、各デバイスに固有の他の値(UDIDなど)があります。他のオプションは、ユーザーが自分自身を表すアドレス帳から連絡先を選択し、そのデータを使用させることです。

1
追加された
1:「アンリ」や「ゲストプレイヤー」のように、プレイ中のGUIに表示する名前を使用します。 2:演奏結果は、アプリケーション外の他のプレイヤーとの比較のためにエクスポートできます。
追加された 著者 JOG,
それはうまくいく!しかし、アイデアは、ユーザーが最初にアプリを起動するとすぐにプレイできるように設定手順をスキップすることです。それがすべて可能ならば。このテキストを質問に追加します。
追加された 著者 JOG,
私は同意する、それは私が質問を投稿する理由です。 :)どのように多くのユーザーがデバイス名を変更するのだろうか。また、私は最近、私の名前を適切に選ぶために、この目的のために新しい連絡先を作成しなければなりませんでした。それは複数のシングルタップです。 (私は自分自身のポストを "this"または "self"と呼ぶ傾向があり、そのアプローチをさらに悪化させた。):)
追加された 著者 JOG,
次に、2番目の提案を使用して、ABAddressBookを使用して連絡先カードをリストから選択させてみましょう。リストからタップした最初の起動は、正直言ってユーザーとあなたの両方にとって簡単です。
追加された 著者 Henri Normak,
私はそれを得るが、間に1つのタップを持つことは、浸漬に影響を与えてはならない。さらに、私は本当に奇妙な名前を持つことは、UITableViewの単一のセルをタップすると、より気を散らすことになると思います。
追加された 著者 Henri Normak,
それは本当です、私はいくつかの統計情報を持っているデバイスは非常に異なる名前を持って、いくつかは人の名前を持って、他はデフォルトのものを持って、3番目のセクターはあいまいな名前を持っています。
追加された 著者 Henri Normak,
NSString *dname=[[UIDevice currentDevice] name];
dname=[dname componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"'的"]][0];
0
追加された