How to fix string in objective-c? - ios

I'm having a problem with the correct answer
When the user types in lets say "dog" the answer is right!
But if s/he types in "dog " <--- with a spacebar its wrong,
how do i fix this:
Code:
- (IBAction)btncheck:(id)sender {
if ([_textbox.text isEqualToString:#"q"]) {
_keyboard.hidden = YES;
_textXclear.hidden = YES;
}
else {
// Was not correct. Notify user, or just don't do anything
}
and id like to notify user that the answer was not correct by placing an image, how is that done

You could use the method stringByTrimmingCharactersInSet to get rid of leading or trailing spaces:
NSString *string = [_textbox.text stringByTrimmingCharactersInSet: whitespaceCharacterSet];
if (string isEqualToString: "q")
{
//string is wrong? If so, display an error message.
}
else
{
//string is correct, resign first responder
}
You should do a search on NSString in the Xcode help system and read the NSString class reference. There are tons of useful methods in the NSString class for doing things like this.
I'm confused, because in your previous post I thought that the answer "q" was the correct answer. In your code above, anything but q would be correct.
As far as placing an image, the easiest thing to do is probably to put an image view, with image installed, in your view controller, but set it's hidden property to YES. Then, when you decide the user has entered the correct answer, set the image view's hidden property to NO to reveal it.

Related

How to check how much two strings are different

How to compare two strings while some parts of them are same?
Let say I have a string ABCAAAA.
For some reason, only ONE character of the string ABCAAAA can be changed at a time. For example, I can change this string to DBCAAAA.
Now the problem is :
How can I ensure ONLY ONE character is changed each time? Is there a method for NSString to compare how much two strings differ?
Purpose: I put each string into own UITextField to determine whether this one is editable if others had changed. I need to ensure only one is edited at a time. So if one had been edited, I will set UITextField's enable to NO to disable editing.
There is no built-in NSString method available to do what you want. You need to write your own method. Objective-C does let you "extend" classes with new methods to cover cases like this.
This is how I would do it:
#interface NSString(Extend)
-(NSInteger)proximity:(NSString*)otherString;
#end
#implementation NSString(Extend)
-(NSInteger)proximity:(NSString*)otherString
{
NSUInteger length = [otherString length];
if(length != [self length]) return -1;
NSUInteger k;
NSUInteger differences = 0;
for(k=0;k<length;++k)
{
unichar c1 = [self characterAtIndex:k];
unichar c2 = [otherString characterAtIndex:k];
if(c1!=c2)
{
++differences;
}
}
return differences;
}
#end
Then in my code at the place I wanted to check I would say something like
Michael L gave a good answer (+1)
I just wanted to note that if all your text strings are in separate UITextFields, then only one of them can be edited at a time. Therefore I really don't understand what you want to do with enable = NO part.
If text strings must be edited in certain order, just keep count of order by index by yourself.

Method To Delete 2nd Label, Then First Label, Not Functioning Correctly

I know I am missing something obvious, but I just cannot see it. This method is meant to compare the text of a label to the text of a text box, and then delete the text. So if the 1st label reads "Puppy" and the 2nd label reads "Kittens," and the text box says "Kittens," the method should delete the text of the 2nd label and leave the 1st label's text. If the 2nd label is blank, then the method should delete the text of the 1st label.
But no matter how I mess with the method, either it deletes the 2nd label but not the 1st, deletes both of them, or deletes neither of them. Here's what I've tried
(lblFabric1 is the 1st label, lblFabric2 is the 2nd label, txtType is the text box):
-(IBAction)btnDelete:(id)sender
{
if ((self.lblFabric2.text== self.txtType.text))
{
self.lblFabric2.text = #"";
}
else if ((self.lblFabric2.text != self.txtType.text))
{
self.lblFabric1.text=#"";
}
}
It deletes the 2nd label, but not the 1st label. If I try to set the "Else if" to:
else if ((self.lblFabric2.text==#""))
it gives me an error (""Direct comparison of a string literal has undefined behavior.") Am I just going about this the wrong way? What am I missing?
You should not use == or != for string comparison in Objective C. You need to use the isEqualToString or isEqual method.
if (([self.lblFabric2.text isEqualToString:self.txtType.text]))
When you use == or != you are comparing the pointers where the strings are stored.
To compare NSStrings use:
if ([myString1 isEqualToString:myString2])
Documentation
Compairing String literals using == is not guaranteed to behave as you might expect. Use isEqual: or isEqualToString: instead.
See http://nshipster.com/equality/.
When you are comparing NSStrings with == what you are actually comparing are two memory addresses and that is not what you are really intended for. You want to compare the values of two strings what == operator is not suitable for and thus you are getting the warning
Direct comparison of a string literal has undefined behavior.
To compare the values of NSStrings you should use isEqualToString: method. You could have also use isEqual: method derived from NSObject class but that is not suitable for Unicode comparison. So isEqualToString: is always the safest bet.
After using isEqualToString: your code should look something like:
-(IBAction)btnDelete:(id)sender
{
if ([self.lblFabric2.text isEqualToString:self.txtType.text])
{
self.lblFabric2.text = #"";
}
else
{
self.lblFabric1.text=#"";
}
}

Is this the standard way to get text from label and concatenate with string in iOS?

Please bear with me as I'm very new to the world of iOS and Objective-C. I've read Apple's Obj-C primer, as well as a few free ones provided on the web.
On a button press, I'm trying to simply take the text of a label and concatenate it with a string. My mindset is still very much in Android/Java and how simple it could be, but I'm having trouble here. Nonetheless here is my code:
- (IBAction)myButton:(UIButton *)sender {
self.myLabel.text = [self.myLabel.text stringByAppendingString:#"obj-c is hard =/"];
}
It seems pretty standard, but I can imagine myself doing this often so I want to make sure this is correct or what other ways are there to do this?
Yes this is correct way. And if you want to use another method then use this one
self.myLabel.text = [NSString stringWithFormat:#"%# obj-c is hard =/",self.myLabel.text];
It is the standard way to join string.As ios updated syntaxes to make it easy like NSArray and NSDictiornary delaration but for concatenation it has not declared any shortcut way.
Have a look at this
OR
you can use a trick to simplify concatenation of string.Pass a parameter to macro and use following joining literal syntax.
#define STRING(text) #""text""
#implementation SPTViewController
- (void)viewDidLoad
{
NSString *joinedFromLiterals =STRING(#"Congratulations!, ") #"I " #"really " #"enjoy " #"carpenting!";
NSLog(#"joined string %#",joinedFromLiterals);
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
output is ---------
joined string Congratulations!, I really enjoy carpenting!
Yes, this is correct, but there is a gotcha. If you haven't previously set the value of self.myLabel.text, it will be nil by default. Then the result of calling any method (like [self.myLabel.text stringByAppendingString:#"obj-c is hard =/"]) will also be nil, so myLabel will still have empty text. The way Objective-C handlesnil values is different than handling null in Java.
So to be safe, initialize label's text first:
self.myLabel.text = #"";
You are doing it right. Sure Objective-C is a bit more verbose than C# or Java or even Visual Basic .net (as I used to work on all those languages) but don't be bugged by those long method names. Although some #defines can be very helpful like (rewritten as C inline function):
static inline __attribute__((always_inline))
__attribute__((format(NSStirng, 1, 2)) NSString *SKSTR(NSString *fmt, ...)
{
va_list args;
va_start(args, fmt);
NSString *string = [[NSString alloc] initWithFormat:fmt arguments:args];
va_end(args);
#if !__has_feature(objc_arc)
[string autorelease];
#endif
return string;
}
Hope the __attribute__s and #ifs does not confuse you - you can safely ignore them.
To use:
self.label.text = SKSTR(#"%#, ugh!", self.label.text); // just like NSLog or snprintf :)

Taking NSString and modifying it for another NSString?

I have a NSString that's giving out input values on a control.
I want to take these values and convert them for user display. AKA, Value 0.7 is 1, value 1.3 is 5. etc.
Ive tried writing an if statement, such as
if self.label.text = 0.7
self.labelone.text = 1
But I cant figure out where it should be written or what code I should be using.
I only need 6 values so even though its a messy way to implement it, I dont mind that much.
Ive searched many resources and I cannot find anything or anyone trying to attempt something similar, which leads me to believe its either incredibly simple, or I'm missing out on something incredibly simple.
Here is the code for the UILabel I'm trying to convert and modify
- (IBAction)rotaryKnobDidChange
{
self.label.text = [NSString stringWithFormat:#"%.3f", self.rotaryKnob.value];
self.slider.value = self.rotaryKnob.value;
}
To compare two variables you should use == instead of =. And you're trying to compare CGFloats with NSStrings.
Use something like this:
if([yourLable.text isEqualToString: #"0.7"]){
[otherLable setText: #"1"];
} else {
if ([yourLable.text isEqualToString: #"1.3"]){
[otherLable setText: #"5"];
}
}
The simple answer to your question:
if ([self.label.text isEqualToString:#"0.7"])
self.labelone.text = #"1";
else if ([self.label.text isEqualToString:#"1.3"])
self.labelone.text = #"5";
But I don't think this is really the code you want.

How to Get the Title of a HTML Page Displayed in UIWebView?

I need to extract the contents of the title tag from an HTML page displayed in a UIWebView. What is the most robust means of doing so?
I know I can do:
- (void)webViewDidFinishLoad:(UIWebView *)webView{
NSString *theTitle=[webView stringByEvaluatingJavaScriptFromString:#"document.title"];
}
However, that only works if javascript is enabled.
Alternatively, I could just scan the text of the HTML code for the title but that feels a bit cumbersome and might prove fragile if the page's authors got freaky with their code. If it comes to that, what's the best method to use for processing the html text within the iPhone API?
I feel that I've forgotten something obvious. Is there a better method than these two choices?
Update:
Following from the answer to this question: UIWebView: Can You Disable Javascript? there appears to be no way to turn off Javascript in UIWebView. Therefore the Javascript method above will always work.
For those who just scroll down to find the answer:
- (void)webViewDidFinishLoad:(UIWebView *)webView{
NSString *theTitle=[webView stringByEvaluatingJavaScriptFromString:#"document.title"];
}
This will always work as there is no way to turn off Javascript in UIWebView.
WKWebView has 'title' property, just do it like this,
func webView(_ wv: WKWebView, didFinish navigation: WKNavigation!) {
title = wv.title
}
I don't think UIWebView is suitable right now.
If Javascript Enabled Use this :-
NSString *theTitle=[webViewstringByEvaluatingJavaScriptFromString:#"document.title"];
If Javascript Disabled Use this :-
NSString * htmlCode = [NSString stringWithContentsOfURL:[NSURL URLWithString:#"http://www.appcoda.com"] encoding:NSASCIIStringEncoding error:nil];
NSString * start = #"<title>";
NSRange range1 = [htmlCode rangeOfString:start];
NSString * end = #"</title>";
NSRange range2 = [htmlCode rangeOfString:end];
NSString * subString = [htmlCode substringWithRange:NSMakeRange(range1.location + 7, range2.location - range1.location - 7)];
NSLog(#"substring is %#",subString);
I Used +7 and -7 in NSMakeRange to eliminate the length of <title> i.e 7
Edit: just saw you found out the answer... sheeeiiitttt
I literally just learned this! To do this, you don't even need to have it displayed in UIWebView. (But as you are using it, you can just get the URL of the current page)
Anyways, here's the code and some (feeble) explanation:
//create a URL which for the site you want to get the info from.. just replace google with whatever you want
NSURL *currentURL = [NSURL URLWithString:#"http://www.google.com"];
//for any exceptions/errors
NSError *error;
//converts the url html to a string
NSString *htmlCode = [NSString stringWithContentsOfURL:currentURL encoding:NSASCIIStringEncoding error:&error];
So we have the HTML code, now how do we get the title? Well, in every html-based doc the title is signaled by This Is the Title
So probably the easiest thing to do is to search that htmlCode string for , and for , and substring it so we get the stuff in between.
//so let's create two strings that are our starting and ending signs
NSString *startPoint = #"<title>";
NSString *endPoint = #"</title>";
//now in substringing in obj-c they're mostly based off of ranges, so we need to make some ranges
NSRange startRange = [htmlCode rangeOfString:startPoint];
NSRange endRange = [htmlCode rangeOfString:endPoint];
//so what this is doing is it is finding the location in the html code and turning it
//into two ints: the location and the length of the string
//once we have this, we can do the substringing!
//so just for easiness, let's make another string to have the title in
NSString *docTitle = [htmlString substringWithRange:NSMakeRange(startRange.location + startRange.length, endRange.location)];
NSLog(#"%#", docTitle);
//just to print it out and see it's right
And that's really it!
So basically to explain all the shenanigans going on in the docTitle, if we made a range just by saying NSMakeRange(startRange.location, endRange.location) we would get the title AND the text of startString (which is ) because the location is by the first character of the string.
So in order to offset that, we just added the length of the string
Now keep in mind this code is not tested.. if there are any problems it might be a spelling error, or that I didn't/did add a pointer when i wasn't supposed to.
If the title is a little weird and not completely right, try messing around with the NSMakeRange-- I mean like add/subtract different lengths/locations of the strings --- anything that seems logical.
If you have any questions or there are any problems, feel free to ask. This my first answer on this website so sorry if it's a little disorganized
Here is Swift 4 version, based on answer at here
func webViewDidFinishLoad(_ webView: UIWebView) {
let theTitle = webView.stringByEvaluatingJavaScript(from: "document.title")
}
I dońt have experience with webviews so far but, i believe it sets it´s title to the page title, so, a trick I suggest is to use a category on webview and overwrite the setter for self.title so you add a message to one of you object or modify some property to get the title.
Could you try and tell me if it works?
If you need it frequently in your code, i suggest you to add a func into "extension UIWebView" like this
extension UIWebView {
func title() -> String {
let title: String = self.stringByEvaluatingJavaScript(from: "document.title")!
return title
}
}
alternatively its better to use WKWebView.
Unfortunately, its not well supported in ARKit. I had to give up on WKWebView. I couldnt load the website into the webView. If someone has a solution to this issue here -> i have a simlar problem, it would help greatly.

Resources