2

When comparing two arabic strings that have special characters like "إ " "أ" The comparison always fail

NSString* string1 = @"الإجمالي";
NSString* string2 = @"الإجمالي";

BOOL ifEqual ;

if([string1 isEqualToString:string2]){
    ifEqual = YES;
}else{
    ifEqual = NO; //Answer is NO
}
STF
  • 1,485
  • 3
  • 19
  • 36
Bassant Ashraf
  • 1,531
  • 2
  • 16
  • 23

2 Answers2

2

The two strings contain the "إ" character in a different representation: The first string as one character ("precomposed representation"):

U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW

and the second string as two characters ("decomposed representation")

U+0627 ARABIC LETTER ALEF
U+0655 ARABIC HAMZA BELOW

If you convert both strings to the precomposed representation then they compare as equal:

NSString* string1 = @"الإجمالي";
NSString* string2 = @"الإجمالي";

string1 = string1.precomposedStringWithCanonicalMapping;
string2 = string2.precomposedStringWithCanonicalMapping;

BOOL ifEqual ;

if ([string1 isEqualToString:string2]) {
    ifEqual = YES; //Answer is YES
} else {
    ifEqual = NO;
}

Swift string comparison handles that automatically:

let string1 = "الإجمالي"
let string2 = "الإجمالي"

print(string1 == string2)
// true
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 1
    I think you'll find Objective-C handles this "automatically" as well, see the answer I added. Swift isn't always better ;-) – CRD May 08 '17 at 21:26
  • @CRD: You are right. I *thought* that I tried that, but apparently I made some mistake. Your's is the correct answer. – Martin R May 08 '17 at 21:29
2

The problem you are having is due to isEqualToString: performing a literal comparison, that is the sequence of bytes that make up the two strings must be exactly the same.

Your two strings look the same but are constructed differently, one uses the single Unicode code point for ARABIC LETTER ALEF WITH HAMZA BELOW, the other uses two code points ARABIC LETTER ALEF and ARABIC HAMZA BELOW to produce the same character - these two forms are called precomposed and decomposed respectively.

The standard string compare: family of methods (compare:options:, localizedCompare: et al) default to considering composed characters, the forms which take an option can be set to behave like isEqualToString by specifying NSLiteralSearch.

So just change your code to:

ifEqual = [string1 compare:string2] == NSOrderedSame;

and you will get the answer you expect.

CRD
  • 52,522
  • 5
  • 70
  • 86