2011-11-24 2 views
13

장치 이름에서 사용자 이름 을 추출하는 기능을 만들었습니다.기기에서 사용자 이름을 찾는 더 나은 방법은 무엇입니까?

은 사용자가 앱을 처음 시작할 때을 바로 재생할 수 있도록 설정 단계를 건너 뜁니다.

이것은 사용자의 이름을 보유하기 위해 장치 이름을 절대로 믿을 수 없으므로 최적의 방법이 아닙니다.입니다. 질문 : 이 작업을 수행하는 더 좋은 방법은 무엇입니까?

아래 내 기능이 올바른 이름을 가져옵니다 ...

  • ... 장치의 기본 이름이 영어 ("사나의 아이팟")
  • ... 변경되지 않은 경우,
  • ... 프랑스어 등으로 ("iPod de Sanna")
  • ... 이름이 S로 끝나지 않는 경우 스웨덴어 및 이와 유사한 ("Sannas iPod") ("Johannes iPod"=> "Johanne "하지만 Johannes는 올바른 것으로 반환해야하며 이름 자체는 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과 같은 다른 서비스에 연결되어 있지 않지만 모든 사용자는 사용자 이름이 필요합니다. 이름을 어떻게 알 수 있니?

+0

는 서비스입니다 응용 프로그램 외부에서 사용할 수 있습니까? 예를 들어 PC에서 말이죠? –

+0

'[[UIDevice currentDevice] name]'은 당신이 원하는 것을 반환합니까? –

+0

@HenriNormak : 아니요, iPhone/iPod 용 앱입니다. 기본적으로 어디에도 연결하지 않아야합니다. – JOG

답변

1

아이팟과 아이폰을위한 것일 뿐인 이유는 무엇입니까? 웹 서비스 용 장치를 식별해야하는 경우 각 장치에 고유 한 다른 값 (예 : UDID)이 있습니다. 다른 옵션은 사용자가 자신을 나타내는 주소록에서 연락처를 선택하고 해당 데이터를 사용하게하는 것입니다.

+1

1 : 예를 들어 "Henri"또는 "Guest player"와 같이 GUI를 연주하는 사람의 이름을 표시합니다. 2 : 게임 결과를 응용 프로그램 외부의 다른 플레이어와 비교하여 내보낼 수 있습니다. – JOG

+0

두 번째 제안을 사용하여 ABAddressBook을 사용하여 목록에서 연락처 카드를 선택하게하십시오. 처음 시작한 사람은 목록에서 한 번 탭하면 정직하게 사용자와 사용자 모두에게 더 쉽게 보이게됩니다. –

+0

그게 효과가있다! 그러나 아이디어는 처음으로 앱을 시작할 때 사용자가 바로 게임을 할 수 있도록 설정 단계를 건너 뛰는 것입니다. 그것이 가능하다면. 이 텍스트를 질문에 추가하겠습니다. – JOG

4

다음은 모든 이름을 가진 대체 방법입니다. 또한 "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]; 
+0

"Sannas iPod"에서는 작동하지 않습니다. 맞습니까? – JOG

+0

나는이 메서드가 작동하고 단지 하나의 이름을 반환한다고 믿는다. lastName이 있는지 확인하지 않기 때문에 "사용"부분이 폭발합니다. –

+0

NSCharacterSet에이 문자열을 사용했습니다 : @ "" '\\ ". Apple이 장치 이름에 사용하는 곡선 UTF8 어포 스트로피를 포함합니다. –

0
NSString *dname=[[UIDevice currentDevice] name]; 
dname=[dname componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"'的"]][0]; 
8

나는 리키 Helegesson의 대답에 개선을 제안하고 싶습니다. 그것은 다음과 같은 특징을 가지고 있습니다;

  • 정규식을 사용하기 때문에 효율성은 떨어지지 만 조금 작지만 한 번만 호출해야한다고 생각합니다.
  • "ipod", "iPhone"및 "iPad"뿐만 아니라 "phone"도 포함시켜야했습니다.
  • "iPad", "iPhone"등의 직전에는 "s"만 제거됩니다. , 그러나 문자열의 끝에서만.
  • "iPad 시뮬레이터"에서와 같이 첫 단어 일 때 "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. 정규식 세 부분을 가지고;
    1. 문자열의 시작 부분에서는 "iPhone", "iPod", "iPad"또는 "phone"과 선택어 "de"가 일치하지 않지만 일치하지 않습니다. 문자열, 경기 끝에
    2. 과 (와 옵션 "의"(반환되지 않은) 한 후 "아이 패드", "아이폰", "아이팟"또는 "전화"뒤에 단어를 반환하는 반환되지 않습니다).
    3. 이 일치는 이전과 동일하지만 중국어 장치 이름에 적용됩니다. (트래비스 웜의 제출에서 적응. 그 잘못된 경우. 알려주세요)
    4. 일치하고 이전 규칙과 일치하지 않는 단어를 반환합니다. 모든 경기를 통해
  2. 으로 반복,이를 활용하고 배열에 추가합니다.
  3. 배열을 반환하십시오.

"iPad"이전에 아포스트로피없이 이름이 "s"로 끝나는 경우 "s"의 일부인지 알아내는 확실한 방법이 없기 때문에 이름을 변경하려고하지 않습니다. 그 이름의 이름 또는 복수형.

즐기십시오!

3
내가 스위프트에 원래 Owen Godfrey 대답을 변환 User's iPhone 6S 또는 iPhone 5 de User처럼 이상의 패턴을 지원하기 위해 RegExpr는 업데이트되었습니다

...

나는 여기에 요점 만들었습니다 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..<result.numberOfRanges { 
       if !NSEqualRanges(result.rangeAtIndex(i), rangeNotFound) { 
        nameParts.append((deviceName as NSString).substringWithRange(result.rangeAtIndex(i)).capitalizedString) 
       } 
      } 
     } 

     if nameParts.count > 0 { 
      username = nameParts.joinWithSeparator(" ") 
     } 
    } 
    catch { NSLog("[Error] While searching for username from device name") } 

    return username 
} 
} 
관련 문제