method for Comparing two NSString for spelling mistakes iPhone programming - objective-c

I am writing an iOS app for a game that is similar to Hangman, except that the player is required to guess the secret word one letter at a time, starting with the first letter. The secret word is displayed as asterisks (*) in a UITextField at the beginning of the game.
When the player guesses the first letter, the program should compare it against the secret word to see if the letter is correct. If the guess is correct, the app should replace the first asterisk with the correct letter. If the guess is incorrect, some other action will be taken. The player repeats this process one letter at a time until the secret word has been completely spelled out.
Here is the code I am currently using to check the guessed letter against the secret word, but it is not working properly.
-(void) checkGameLetter : (NSString *) letterToCheck{
bool match = NO;
NSRange gameLetterRange;
char charToCheck = [letterToCheck characterAtIndex:0];
for(int i = 0; i < self.correctWord.length; i++)
{
char tempString = [self.correctWord characterAtIndex:i];
if(charToCheck == tempString){
match = YES;
gameLetterRange = NSMakeRange(i, 1);//location, length
Screen.text =[Screen.text stringByReplacingCharactersInRange:gameLetterRange withString:letterToCheck];
}
}

The thing that's wrong with your code is that nothing in it says which letter of the correct word we are checking against.
For example, suppose the word is "zork" and the user guesses "r". You are trying to walk through "zork" looking to see if "r" matches any letter. But according to your spec, if this is a guess at the first letter, we should just be checking against the first letter ("z") and stop, since the "r" is wrong in that position.
So what you want to write is much simpler than the code you have. You don't want this:
-(void) checkGameLetter : (NSString *) letterToCheck{
You want this:
-(void) checkGameLetter:(NSString*)letterToCheck againstPosition:(NSInteger)position {
And there will be no loop: you will just look right at the letter in that position and see if they are the same.
Finally notice this important fact: == does not compare two strings. It asks whether they are the same object, which they manifestly are not. You want isEqualToString:.

Related

Disable line breaking after certain words

I have few UILabels in my app. All of them are set to be multiline by setting numberOfLines as 0. By this, some of them have 1 line, some have 2. My problem is, that according to grammar of language of this app, certain words should never be at the end of an line.
For example, let have sentence: "John is collecting fossils and stamps".
This line will be long enought for line breaking to appear after word "and". According to grammar, this should not happen, so I want to break line before this word, so instead of this after line break:
John is collecting fossils and
stamps
I want to get:
John is collecting fossils
and stamps
Is it possible to achieve this? I am working with iOS 7 and higher, so need not to care with compatibility with older iOS versions.
Solution is to make a subclass of UILabel with 2 methods. Lets assume, that I only want to disable line breaking after word "a" (similar solution can be with multiple words):
- (void)setText:(NSString*)newText {
[super setText:[self fixSpaces:newText]];
}
- (NSString*)fixSpaces:(NSString*)originalText {
NSMutableString* tempString = [[NSMutableString alloc] initWithString:originalText];
[tempString replaceOccurrencesOfString:#"a " withString:#"a " options:NSLiteralSearch range:NSMakeRange(0, tempString.length)];
return tempString;
}
String that will be replaced is "a ", thats a standard 'a' and space. String that will replace it looks the same on the screen, but it is 'a' and non-breaking space (on MAC - Option + Space). Setting any text in a standard way of setting text to UILabel will always work as desired, but comparing string with text of label will not work (but it is easy to fix that by replacing non-breakable spaces with spaces for comparison). Setting text in storyboard or nib will naturally not work.

Object to input the keyboard characters and numbers and dispaly the output in a text field in objective C

I am using NSMutableString object to read input digits from keypad. It is becoming cumbersome with some complex arithmetic operations using this object. Is there any other way to read the input data and display the data in a textfiled?
Below is the code currently being used.
digit = (int)sender.tag;
[displayString appendString: [NSString stringWithFormat:#"%i", digit]];
display.text = displayString;
currentnumber = currentnumber*10 + digit;
It is becoming cumbersome with some complex arithmetic operations using this object.
That's because you're doing things in a cumbersome way. Try this instead:
digit = (int)sender.tag;
currentNumber = currentNumber*10 + digit;
display.text = [NSString stringWithFormat:#"%d", currentNumber];
Don't try to derive the display string separately from the value that you're using for computation. The computation value, currentNumber, is like your data model -- it's the thing that your program is going to operate on. So instead of appending digits to the display string to try to cobble together the string to display, determine the string to display from the number you're working with (or going to work with). That way, if the user hits the √ button, you can do something like:
currentNumber = sqrt(currentNumber);
display.text = [NSString stringWithFormat:#"%d", currentNumber];
You probably should develop a more complete data model than just using a single numeric variable. You want a CalculatorModel class, or something like that, which you can give inputs when the user hits a key, and always get the current output. There's no generic version of that because every app does something different -- the model is a big part of what you bring to the party when you write an app.

how to insert extra glyphs?

I want to an UITextView to switch between two display modes.
In mode 1 it should show abbreviations and in the full word in mode 2. For example "Abbr." vs "abbreviation".
What would be the best way to do this? Keeping in mind that some words can have the same abbreviation and that the user is free to type either the full word or the abbreviation?
So far I tried to subclass NSLayoutManager.
Assuming I get an abbreviated string and I have to draw the full word, I would implement the following method:
-(void)setGlyphs:(const CGGlyph *)glyphs
properties:(const NSGlyphProperty *)props
characterIndexes:(const NSUInteger *)charIndexes
font:(UIFont *)aFont
forGlyphRange:(NSRange)glyphRange
{
NSUInteger length = glyphRange.length;
NSString *sourceString = #"a very long string as a source of characters for substitution"; //temp.
unichar *characters = malloc(sizeof(unichar) * length+4);
CGGlyph *subGlyphs = malloc(sizeof(CGGlyph) * length+4);
[sourceString getCharacters:characters
range:NSMakeRange(0, length+4)];
CTFontGetGlyphsForCharacters((__bridge CTFontRef)(aFont),
characters,
subGlyphs,
length+4);
[super setGlyphs:subGlyphs
properties:props
characterIndexes:charIndexes
font:aFont
forGlyphRange:NSMakeRange(glyphRange.location, length+4)];
}
However this method complains about invalid glyph indices "_NSGlyphTreeInsertGlyphs invalid char index" when I try to insert 4 additional glyphs.
You're barking way up the wrong tree; trying to subclass NSLayoutManager in this situation is overkill. Your problem is merely one of swapping text stretches (replace abbrev by original or original by abbrev), so just do that - in the text, the underlying NSMutableAttributedString being displayed.
You say in a comment "some words map to the same abbreviation". No problem. Assuming you know the original word (the problem would not be solvable if you did not), store that original word as part of the NSMutableAttributedString, i.e. as an attribute in the place where the word is. Thus, when you substitute the abbreviation, the attribute remains, and thus the original word is retained, ready for you when you need to switch it back.
For example, given this string: #"I love New York" You can hide the word "New York" as an attribute in the same stretch of text occupied by "New York":
[attributedString addAttribute:#"realword" value:#"New York" range:NSMakeRange(7,8)];
Now you can set that range's text to #"NY" but the attribute remains, and you can consult it when the time comes to switch the text back to the unabbreviated form.
(I have drawn out this answer at some length because many people are unaware that you are allowed to define your own arbitrary NSAttributedString attributes. It's an incredibly useful thing to do.)

UITextChecker 25 Letter Words

I believe this is an Apple bug, but wanted to run it by you all and see if anyone else had run into the same/similar issues.
Simply, Apple's UITextChecker finds all words 25 letters or more as valid, spelled correctly words. Go ahead and open up Notes on your iOS device (or TextEdit on OS X) and type in a random 24 letter word. Hit enter, underlined red, right? Now add one more letter to that line so it is a 25 letter word. Hit enter again, underline red, right ... nope!
I don't know if this is related, but I have a similar unanswered question out there (UITextChecker is what dictionary?) questioning what dictionary is used for UITextChecker. In /usr/share/dict/words the longest word is 24 letters. Seems rather coincidental that 25 letters would be the first length of word that is not in the dictionary and it is always accepted as a valid word. But I don't know if that word list is the dictionary for UITextChecker.
This is important to note for anyone that might be confirming the spelling of a given word for something like a game. You really don't want players to able to use a random 25 letters to spell a word and most likely score massive points.
Here's my code to check for valid words:
- (BOOL) isValidWord:(NSString*)word {
// word is all lowercase
UITextChecker *checker = [[UITextChecker alloc] init];
NSRange searchRange = NSMakeRange(0, [word length]);
NSRange misspelledRange = [checker rangeOfMisspelledWordInString:word range:searchRange startingAt:0 wrap:NO language:#"en" ];
[checker release];
BOOL validWord = (misspelledRange.location == NSNotFound);
BOOL passOneCharTest = ([word length] > 1 || [word isEqualToString:#"a"] || [word isEqualToString:#"i"]);
BOOL passLengthTest = ([word length] > 0 && [word length] < 25); // I don't know any words more than 24 letters long
return validWord && passOneCharTest && passLengthTest;
}
So my question to the community, is this a documented 'feature' that I just haven't been able to locate?
This is likely to be caused by the algorithm used for spell-checking itself although I admit it sounds like a bit of a hole.
Even spell-checkers that use a dictionary often tend to use an algorithm to get rid of false negatives. The classic is to ignore:
(a) single-character words followed by certain punctuation (like that (a) back there); and
(b) words consisting of all uppercase like NATO or CHOGM, assuming that they're quite valid acronyms.
If the algorithm for UITextChecker also considers 25+-letter words to be okay, that's just one of the things you need to watch out for.
It may well be related to the expected use case. It may be expected to be used as not so much for a perfect checker, but more as a best-guess solution.
If you really want a perfect filter, you're probably better off doing your own, using a copy of the dictionary from somewhere. That way, you can exclude things that aren't valid in your game (acronyms in Scrabble®, for example).
You can also ensure you're not subject to the vagaries of algorithms that assume longer words are valid as appears to be the case here. Instead you could just assume any word not in your dictionary is invalid (but, of course, give the user the chance to add it if your dictionary is wrong).
Other than that, and filing a query/bug with Apple, there's probably not much else you can do.

How to find out if there is an "." in an NSString?

Have got an
NSString *str = #"12345.6789"
and want to find out if there is that "." character inside of it. I'm afraid that there are ugly char-encoding issues when I would just try to match an #"." against this? How would you do it to make sure it always finds a match if there is one?
I just need to know that there is a dot in there. Everything else doesn't matter.
You can use rangeOfString: message to get the range where your "." is.
The prototype is:
- (NSRange)rangeOfString:(NSString *)aString
You can find more info about this message in: Mac Dev Center
There would be something like this:
NSRange range;
range = [yourstring rangeOfString:#"."];
NSLog(#"Position:%d", range.location);
If you need to, there is another message ( rangeOfString:options: ) where you can add some options like "Case sensitive" and so on.
If [str rangeOfString:#"."] returns anything else than {NSNotFound, 0}, the search string was found in the receiver. There are no encoding issues as NSString takes care of encoding. However, there might be issues if your str is user-provided and could contain a different decimal separator (e.g., a comma). But then, if str really comes from the user, many other things could go wrong with that comparison anyway.
To check . symbol, it will be useful.
if ([[str componentsSeparatedByString:#"."] count]>1) {
NSLog(#"dot is there");
}else{
NSLog(#"dot is not there");
}
If what you really want to do is determine whether the string represents a number with a fractional part, a better solution is to feed the string to a number formatter, then examine the number's doubleValue to see whether it has a fractional part.
For the latter step, one way would be to use the modf function, which returns both the fractional part (directly) and the integral part (by reference). If the fractional part is greater than zero (or some appropriately small fraction below which you're willing to tolerate), then the number has a fractional part.
The reason why this is better is because not everybody writes decimal fractions in the “12345.6789” format. Some countries use a comma instead, and I'm sure that's not the only variation. Let the number formatter handle such cases for you.
I wrote a little method to make things a little more natural if you use this sort of thing a whole bunch in your project:
+(BOOL)seeIfString:(NSString*)thisString ContainsThis:(NSString*)containsThis
{
NSRange textRange = [[thisString lowercaseString] rangeOfString:[containsThis lowercaseString]];
if(textRange.location != NSNotFound)
return YES;
return NO;
}
Enjoy!