Voice over doesn't read phone number properly

后端 未结 5 1162
半阙折子戏
半阙折子戏 2020-12-17 03:36

I have phone number in below format

1-1xx-2xx-9565

Currently VO read it as \"One (pause) One x x

相关标签:
5条回答
  • If you want to spell all characters individually, a simple solution is to separate the characters by a comma ",".

    You can use a String extension to convert the string:

    extension String
    {
        /// Returns string suitable for accessibility (voice over). All characters will be spelled individually.
        func stringForSpelling() -> String
        {
            return stringBySeparatingCharactersWithString(",")
        }
    
    
        /// Inserts a separator between all characters
        func stringBySeparatingCharactersWithString(separator: String) -> String
        {
            var s = ""
            // Separate all characters
            let chars = self.characters.map({ String($0) })
    
            // Append all characters one by one
            for char in chars {
                // If there is already a character, append separator before appending next character
                if s.characters.count > 0 {
                    s += separator
                }
                // Append next character
                s += char
            }
    
            return s
        }
    }
    

    And then use it in the code like this:

    myLabel.accessibilityLabel = myString.stringForSpelling()
    
    0 讨论(0)
  • 2020-12-17 03:58

    As of iOS 13 you can use a - NSAttributedString.Key.accessibilitySpeechSpellOut as a accessibilityAttributedLabel to make VoiceOver read each letter of the provided string (or a range of string).

    So for example:

    yourView.accessibilityAttributedLabel = NSAttributedString(string: yourText, attributes: [.accessibilitySpeechSpellOut: true])
    
    0 讨论(0)
  • 2020-12-17 04:02

    Here is the code in Swift

        public func retrieveAccessiblePhoneNumber(phoneNumber: String) -> String {
        // We want to know if a character is a number or not
        let characterSet = NSCharacterSet(charactersInString: "0123456789")
    
        // We use this formatter to spell out individual numbers
        let numberFormatter = NSNumberFormatter()
        numberFormatter.numberStyle = .SpellOutStyle
    
        var spelledOutComponents = [String]()
        let range = Range<String.Index>(start: phoneNumber.startIndex, end: phoneNumber.endIndex)
    
        // Loop over the phone number add add the accessible variants to the array
        phoneNumber.enumerateSubstringsInRange(range,
            options: NSStringEnumerationOptions.ByComposedCharacterSequences) { (substring, substringRange, enclosingRange, stop) -> () in
                // Check if it's a number
                if let substr = substring where substr.rangeOfCharacterFromSet(characterSet) != nil {
                    if let number = Int(substr) {
                        // Is a number
                        let nsNumber = NSNumber(integer: number)
                        spelledOutComponents.append(numberFormatter.stringFromNumber(nsNumber)!)
                    }
                } else {
                    // Is not a number
                    spelledOutComponents.append(substring!)
                }
        }
    
        // Finally separate the components with spaces (so that the string doesn't become "ninefivesixfive".
        return spelledOutComponents.joinWithSeparator(" ")
    }
    
    0 讨论(0)
  • 2020-12-17 04:17

    Let's break down what is happening. VoiceOver doesn't know that the text you are presenting is a phone number and treats it like a sentence of text. In that text it tries to find distinct components and read them appropriately. For example, the text "buy 60 cantaloupes" has 3 components, "buy", "60", and "cantaloupes". The first is text and is read as text, the second is purely numerical and is best read out as "sixty", and the third is read as text.

    Applying the same logic to your phone number.

    (I'm not talking about actual implementation, just reasoning.)

    If you read 1-1xx-2xx-9565 from the left to the right then the first distinct component is "1" which in it self is numerical and is read as "1". If the phone number would have started with "12-1xx" then the first component would have been read as "twelve" because its purely numerical.

    The next component is "1xx" or "-1xx" depending on how you look at it. In either case it is a combination of numbers and letters, e.g. it is not purely numerical and is thus read out as text. If you include the "-" in that component is interpreted as a hyphen which isn't read out. That is why the the "-" is never read out for that component. The next component ("-2xx") is treated in the same way.

    The final component is "-9565" which turns out to be a valid number. As seen in the cantaloupe sentence, VoiceOver reads this as a number in which case the "-" is no longer interpreted as a hyphen but as a "minus sign".

    Getting VoiceOver to read your own text

    On any label, view or other element in your application that is used with Voice Over, you can supply your own "accessibility label" when you know more about how you want the text to be read. This is done by simply assigning your own string to the accessibilityLabel property.

    Now, you can create a suitable string in many different ways, a very simple one in your case would be to just add spaces everywhere so that each number is read individually. However, it seems a bit fragile to me, so I went ahead and used a number formatter to translate the individual numbers to their textual representations.

    NSString *phoneNumber = @"1-1xx-2xx-9565";
    
    // we want to know if a character is a number or not
    NSCharacterSet *numberCharacters = [NSCharacterSet characterSetWithCharactersInString:@"0123456789"];
    
    // we use this formatter to spell out individual numbers
    NSNumberFormatter *spellOutSingleNumber = [NSNumberFormatter new];
    spellOutSingleNumber.numberStyle = NSNumberFormatterSpellOutStyle;
    
    NSMutableArray *spelledOutComonents = [NSMutableArray array];
    // loop over the phone number add add the accessible variants to the array
    [phoneNumber enumerateSubstringsInRange:NSMakeRange(0, phoneNumber.length)
                                    options:NSStringEnumerationByComposedCharacterSequences
                                 usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
                                     // check if it's a number
                                     if ([substring rangeOfCharacterFromSet:numberCharacters].location != NSNotFound) {
                                         // is a number
                                         NSNumber *number = @([substring integerValue]);
                                         [spelledOutComonents addObject:[spellOutSingleNumber stringFromNumber:number]];
                                     } else {
                                         // is not a number
                                         [spelledOutComonents addObject:substring];
                                     }
                                 }];
    // finally separate the components with spaces (so that the string doesn't become "ninefivesixfive".
    NSString *yourAccessiblePhoneNumber = [spelledOutComonents componentsJoinedByString:@" "];
    

    The result when I ran this was

    one - one x x - two x x - nine five six five
    

    If you need to do other modifications to your phone numbers to get them to read appropriately then you can do that. I suspect that you will use this is more than one place in your app so creating a custom NSFormatter might be a good idea.


    Edit

    On iOS 7 you can also use the UIAccessibilitySpeechAttributePunctuation attribute on an attributes string to change how it is pronounced.

    Speech Attributes for Attributed Strings

    Attributes that you can apply to text in an attributed string to modify how that text is pronounced.

    UIAccessibilitySpeechAttributePunctuation

    The value of this key is an NSNumber object that you should interpret as a Boolean value. When the value is YES, all punctuation in the text is spoken. You might use this for code or other text where the punctuation is relevant.

    Available in iOS 7.0 and later.

    Declared in UIAccessibilityConstants.h.

    0 讨论(0)
  • 2020-12-17 04:20

    Just Add a comma to each digit of the last number and after the last digit as well,. this will make sure voice over reads the last number as same as previous numbers.

    example your number :- 1-1xx-2xx-9565 accessibility label :- 1-1xx-2xx-9,5,6,5,

    0 讨论(0)
提交回复
热议问题