I have this basic text-checking code that has worked fine up until iOS 7:
NSMutableCharacterSet*testchars=[NSCharacterSet alphanumericCharacterSet];
[testchars addCharactersInString:#".-"];
BOOL didFindBadCharacters = ([userInput rangeOfCharacterFromSet:[testchars invertedSet]].location != NSNotFound);
The simple idea here is to check the user's input which is userInput and find a BOOL that is true if any of the characters the user entered are not alphanumeric or contain a dot or dash. That is, those entries are fine, but a space, or a symbol, are not fine.
Until iOS 7, this worked. I don't understand why this would be different with iOS 7, but now if the user enters a dot or a dash, the BOOL returns as true when I've logged to make sure there is no other character, such as a space, triggering the error instead.
Why would this fail on iOS 7? Seems like basic language features.
Why would this fail on iOS 7?
My only guess as to why this would be different in iOS 7 is that they have fixed a bug: prior to iOS 7, cocoa used to return a mutable character set for the built-in character sets.
The documentation does not say that the NSCharacterSet returned from alphanumericCharacterSet should be mutable, so the assignment on the first line is invalid, even though the compiler does not complain.
This should fix the problem:
NSMutableCharacterSet*testchars = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
I'm not sure that the first line of your code does what you think it does. It probably assigns a NSCharacterSet object to testchars (that is, a non-mutable set). As a result, the 2nd line probably does nothing. Try initing your testchars as a proper NSMutableCharacterSet, I bet your code would work then.
As #dasblinkenlight correctly suggests, this should do the trick:
NSMutableCharacterSet *testchars = [[NSCharacterSet alphanumericCharacterSet] mutableCopy];
Related
I'm taking the Stanford iPad and iPhone developer course online at Stanford using Swift and working on creating a Calculator application. (Still a bit new to programming.)
However, it keeps crashing with the error message whenever I select an operator from the calculator.
operandStack = [36.0]
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
and then when I look in ViewController to see what part of the source code is highlighted. It is this:
NSNumberFormatter().numberFromString(display.text!)!.doubleValue }
the error message under this though, reads:
THREAD 1:EXC_BAD_INSTRUCTION(code:EXC_1386_INVOP,subcode=0x0)
I don't understand what's going on, since I entered the code, word for word from the lecture.
Any help is appreciated!
Thanks in advance!
I am stuck at that part of the course too!
I think that apple recently made changes to NSNumberFormatter's numberFromString method. Because when I printed out display.text!, there was nothing wrong. In other words, it does not found nil while unwrapping that part.
Another part we are unwrapping is here, at the second ! mark, we unwrap only this part:
NSNumberFormatter().numberFromString(display.text!)
But we have an error out of this, so numberFromString should be returning nil.
But in the videos, it doesn't. It perfectly turns floating point number strings (such as "36.0") to NSNumber, then to Double.
And since your question was asked on May 20th and I could not find any "old" questions, I think Apple had changed the code on numberFromString.
Edit: I did something crazy and used Find & Replace (command + F) to replace all "Double"s to "Int"s in my code. The multiplication part works well now, I think the problem is about the "." part on Doubles.
Edit 2: I solved it. Some countries such as US use "." to separate decimals and some others such as Turkey use "," to do it. It works on video because he's doing it on US.
NSNumberFormatter has a property called decimalSeparator. We have to set it to ".". I did the following changed to my code and it worked perfect.
var displayValue: Double {
get {
var formatter = NSNumberFormatter()
formatter.decimalSeparator = "."
return (formatter.numberFromString(display.text!)!.doubleValue)
}
set {
display.text = "\(newValue)"
userIsInTheMiddleOfTypingNumber = false
}
}
"found nil while unwrapping an Optional" means that you have a variable that may or maynot have a value, when you use the operator ! you are telling swift "Trust me there is a value in there" however if there is not swift will throw a exception as the one you just saw.
The best way to avoid this is checking before use:
if let value = display.text{
//if your code get here value is safe to use
NSNumberFormatter().numberFromString(value).doubleValue
}
Can you say me what is false in this code? I like to check if cydia.app is installed on every launch and if Cydia is installed the Lable should change and a button should be enabled but nothing happens.
Here is the code:
NSString *filePath = #"/Applications/Cydia.app";
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]){
Lable.text = #"You are jailbroken";
Button.enabled = YES;
}
You need to enclose both lines with parentheses if you want to enable the button, and remove the semicolon after the conditional. Basically, your code should look like this:
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"cydia://"]]){
Lable.text = #"You are jailbroken";
Button.enabled = YES;
}
Otherwise, what you are currently using after the conditional statement, by inserting a semicolon, is actually a null statement. Even if you remove the semicolon, only the first line will be executed. Therefor, you need to remove the semicolon, and insert curly brackets to set the scope of the conditional.
Edit:
Perhaps you might need to try building the path instead of hardcoding it:
NSString* filePath = [NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES) stringByAppendingPathComponent: #"cydia.app"];
If the file still doesn't exist, try to list the files and directories in the NSApplicationDirectory to see if the file actually exists, or you need to search elsewhere (maybe even a subfolder).
Set some breakpoints in your code so that when you debug your code you can see what your conditional statement is evaluating to and depending on that, then see what is happening with the code in your if structure. In many cases, like this, simply setting breakpoints and quickly stepping over your code will lead you to your resolution faster than posting up a question on the Internet, not that people won't help you, but you won't be held up and can continue working.
Cheers.
I am getting a request data and putting it in NSString. after that, I am getting the following string,
_VIEWSTATE=%2FwEPDwULLTE1MjI5NTA5MzBkZBfGgdOVhk6K8WsSgq64ngCpAncw&_EVENTVALIDATION=%2FwEWBgKdhbkbAvOQn7cGApKGyNkMAsKL2t4DApSbgLYHArS6otoP2nSQkmm0E6zJe2u91W5ntimqJ18%3D&x-rim-queue-id=MyOfflineQueue&form_id=723&txt2=siddhesh.b.chavan%40gmail.com&btnSubmit=Submit&x-rim1-request1-title=SignatureShouldBeDoneHere&x-rim-request-title=iPhone3+4%2F6%2F2011+3%3A57%3A21+AM
The thing I have to ask is, I want to get the "form_id" from this string which is "723".
so, How do I get that??
I want to get the form_ID for a request everytime. So, kindly help me out of this.
Thanking you.
These options are more intended for URL arguments parsing, which you are trying to do.
1. Range search : for a word, a character
most efficient but can be fastidious to write... (and read!)
See rangeOfString: and its friends on NSString documentation
2. Split
quick and elegant to write, but not so efficient
Since it is a URL argument style string, it is easily parsable by splitting on & and = witch can be done easily using componentsSeparatedByString: or componentsSeparatedByCharactersInSet:
3. Regular expressions
clean code, powerful
Regular expressions are imho the best choice to manipulate text, but they can be harder to use/learn than previous solutions. To use regular expressions I suggest two options:
iPhone OS >= 3.2 has regular expressions :
NSString rangeOfString:options:NSRegularExpressionSearch
But this is close to option 1.
RegexKitLit, with provides an excellent regular expression engine on OSX/iOS would provide, imho, the best and most powerful solution to your problem (and many others!!!)...
4. Other Kits/API/SDK
the missing api/toolkit/sdk? don't write code thousands people already wrote...
I wished that NSURL would support URL arguments, for parsing and build urls... but it does not.
I don't know a good URL parsing/toolbox library that offers such URL Arguments manipulation tools (Google Toolbox does not provide such URL arguments tools except for escaping which is already really useful) but I'm sure that exists! And a good library, with tested and reliable code would be for sure your best solution...
5. Others... there are many
I forgot to mention NSScanner which I never really looked into (bad me)
More generally, Apple documentation on this topic is interesting.
if you would like to try this: Let me know if it works.
NSInteger formId;
//separate the whole string first by "&" characters
NSArray *array = [myString componentsSeparatedByString:#"&"];
for (NSString *queryString in array)
{
//for every separated string, look if you have the "form_id" key
NSRange range = [queryString rangeOfString:#"form_id=" options:NSLiteralSearch];
if (range.location != NSNotFound)
{
NSLog(#"form_id query string does exist");
//form_id= has 7 characters, pick the character which comes after the "=" sign.
NSString *value = [queryString substringFromIndex:8];
formId = [value integerValue];
}
}
That solution is assuming that you only have 1 "form_id".
Try this :
[myString substringToIndex:index];
[myString substringFromIndex:index];
[myString substringWithRange:range];
Or
if ( [yourString rangeOfString:#"form_id"].location == NSNotFound )
{
NSLog(#"form_id not found");
}
Use 'rangeOfString:options:range:' start by searching the entire string for "form_id=" and then search from where that was found to for an "&". You will need to handle the case where the ampersand isnt found (when form_id is the last in the list).
You can use NSScanner object too. Like-
NSScanner *scanner = [NSScanner scannerWithString:reqData];
[scanner scanUpToString:#"form_id" intoString:nil];
[scanner scanUpToString:#"&" intoString:&strObj];
valueStr = [strObj substringFromIndex:1];
First off, I'm a complete beginner.
That said, I thought an ambitious longer-term project/learning experience would be to create an app that displayed daily quotes, like those cheesy day-by-day calendars our grandmothers have in their bathrooms. I want it to have two per day, each one represented by a tab in a UISegmentedControl. That's the long term. Right now I'd be happy with getting a single day's worth of quotes functioning.
Onto the questions:
How can I get text saved in a .txt or .rtf file to be displayed in a UITextView? Preferably without using 'stringWithContentsOfFile,' since Xcode is telling me that's deprecated.
How can I get content from a different file (or maybe a different portion of the same file...?) to be displayed when the user taps the second segment?
If I can get it running so that those two conditions are met and I understand what's going on, I'll consider the day a success. Thanks!
1.
NSError *error = nil;
NSStringEncoding stringEncoding;
NSString *fileText = [NSString stringWithContentsOfFile:#"/path" usedEncoding:&stringEncoding error:&error];
myTextView.text = fileText;
The error and encoding are optional, and you can pass in nil for both. But if you care about the error, or what encoding the file was in they will have useful info in them after the string is created.
2.
Set the valueChanged outlet in Interface Builder to an IBAction on your controller, such as setSegmentValue:. Then, assuming you have an array of quote strings:
- (IBAction)setSegmentValue:(id)sender {
UISegmentedControl *control = (UISegmentedControl*)sender;
NSString *quote = [quotes objectAtIndex:control.selectedSegmentIndex];
myTextView.text = quote;
}
Even though stringWithContentsOfFile: is deprecated, stringWithContentsOfFile:usedEncoding:error: is not. That is the standard method to use for reading from files.
As for the second question, you simply test the state of the segmented control and perform as action based on it. Admittedly this is a high level answer but should get you going.
I'm converting data (from a web page) to a string). The basic code works (but there's been some subtle change somewhere - maybe on server).
NSLog shows the expected string (maybe 1000 chars long). However, when I float over responseString, it shows "Invalid". Worse, parsing with componentsSeparatedByCharactersInSet does not work.
Ideas?
NSString *responseString;
responseString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSLog([NSString stringWithFormat:#"responsestring ='%#'",responseString]);
if ([responseString compare:#""] != NSOrderedSame) {
lines = [responseString componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:#";"]];
This may happen when the configuration is set to "Release" rather than "Debug" I think.
Do not trust what the debugger says, it is not accurate, this has happened to me and took me a while to realise that the xcode debugger is not always right and should not be trusted, so i no longer trust the debugger and i use nslog statements whenever it tries to tell me something is invalid. So dont worry about it it happens, and when it happened to me I was also parsing responses from some webservice.
Just to be clear -- my experience with seeing "Invalid" in the debugger means that the reference is to an already-released object.
Your question and the comments below seem to suggest that you are thinking "Invalid" is an actual string value -- but are you sure you don't just have a memory management probably?