Sorry for my english, I try to explain better my problem:
I need to parse a math expression and then save the results inside a variable, this is my code:
for (i = -100; i < 100; i = i + step) {
NSError *error = nil;
NSDictionary *variableSubstitutions = [NSDictionary dictionaryWithObject:[NSNumber numberWithDouble:i] forKey:#"x"];
NSNumber *y = [[DDMathEvaluator sharedMathEvaluator] evaluateString:[self convertString:eq.equazione] withSubstitutions:variableSubstitutions error:&error];
NSLog(#"y is: %#",y);
}
The NSLog have always a value, if I try to parse an expression like tan(x) the log never print a nil value, I need to display also the nil value if exist.
I try to check y value, error value but I don't find a way for handle nil value of expression.
This is probably not what you want, if not please update your question.
NSNumber *y = [[DDMathEvaluator sharedMathEvaluator] evaluateString:[self convertString:eq.equazione] withSubstitutions:variableSubstitutions error:&error];
if(y)
NSLog(#"y is: %#", y);
else
NSLog(#"y is: nil");
Related
I'm trying to retrieve data from the iPhone address book and I have some problems.
First of all, I have an array of all contacts (self.allContacts):
ABAddressBookRef abRef = ABAddressBookCreate();
self.allContacts = (NSMutableArray*)ABAddressBookCopyArrayOfAllPeople(abRef);
I also have an array of all properties (each property as string) called self.allKeys.
The crash occurs when I try to get the properties using a property from self.allKeys:
NSString *currentRecord = [[NSString alloc] init];
ABRecordRef currentRecordRef;
ABPropertyID currentFieldProperty;
currentRecordRef = (ABRecordRef)[self.allContacts objectAtIndex:i];
currentFieldProperty = (ABPropertyID)[self.allKeys objectAtIndex:j];
currentRecord = (NSString*)ABRecordCopyValue(currentRecordRef, currentFieldProperty);
The problem is that passing currentFieldProperty to ABRecordCopyValue causes a crash.
self.allContacts is an array of all contacts
self.allKeys is an array of all properties (each property as string)
When trying to retrieve a single property from ABRecordCopyValue it causes an EXC_BAD_ACCESS crash.
Thanks!
Set NSZombieEnabled, MallocStackLogging, and guard malloc in the debugger. Then, when your App crashes, type this in the gdb console:
(gdb) info malloc-history 0x543216
Replace 0x543216 with the address of the object that caused the crash, and you will get a much more useful stack trace and it should help you pinpoint the exact line in your code that is causing the problem.
- More thoughts -
If self.allKeys is indeed
"an array of all properties (each property as string)"
then you should probably get the intValue of the array object (property) since an ABPropertyID is just a typedef int32_t. Something like:
currentFieldProperty = (ABPropertyID)[[self.allKeys objectAtIndex:j] intValue];
ABRecordCopyValue(currentRecordRef, currentFieldProperty)
But we would need to see the values in self.allKeys or how it is populated to be sure.
From ABRecordRef Reference and CFTypeRef Reference
ABRecordCopyValue - Returns the value of a record property.
CFTypeRef ABRecordCopyValue (
ABRecordRef record,
ABPropertyID property
);
Parameters
record - The record containing the property in question.
property - The property of record whose value is being returned.
Return Value
The value of property in record.
And:
ABPropertyID - Integer that identifies a record property.
typedef int32_t ABPropertyID;
- And more troubleshooting ideas -
If the above is not the case, then your crash may be caused when you cast CFTypeRef to NSString * in (NSString*)ABRecordCopyValue(currentRecordRef, currentFieldProperty) so here is a little helper function that might solve that:
- (NSString*)stringValueForCFType:(CFTypeRef)cfValue {
NSString *stringValue = nil;
if (!cfValue) return nil;
CFTypeID cfType = CFGetTypeID(cfValue);
if (cfType == CFStringGetTypeID()) {
stringValue = [[(id)CFMakeCollectable(cfValue) retain] autorelease];
} else if (cfType == CFURLGetTypeID()) {
stringValue = [(NSURL*)cfValue absoluteString];
} else if (cfType == CFNumberGetTypeID()) {
stringValue = [(NSNumber*)cfValue stringValue];
} else if (cfType == CFNullGetTypeID()) {
stringValue = [NSString string];
} else if (cfType == AXUIElementGetTypeID()) {
stringValue = [[GTMAXUIElement elementWithElement:cfValue] description];
} else if (cfType == AXValueGetTypeID()) {
stringValue = [self stringValueForAXValue:cfValue];
} else if (cfType == CFArrayGetTypeID()) {
stringValue = [self stringValueForCFArray:cfValue];
} else if (cfType == CFBooleanGetTypeID()) {
stringValue = CFBooleanGetValue(cfValue) ? #"YES" : #"NO";
} else {
CFStringRef description = CFCopyDescription(cfValue);
stringValue = [(id)CFMakeCollectable(description) autorelease];
}
return stringValue;
}
Then do currentRecord = [self stringValueForCFType:ABRecordCopyValue(currentRecordRef, currentFieldProperty)]; and check to make sure self.allKeys has an object at index j and self.allContacts has an object at index i:
NSString *currentRecord = [[NSString alloc] init];
ABRecordRef currentRecordRef;
ABPropertyID currentFieldProperty;
if (self.allContacts.count > i) {
currentRecordRef = (ABRecordRef)[self.allContacts objectAtIndex:i];
if (self.allKeys.count > j) {
currentFieldProperty = (ABPropertyID)[self.allKeys objectAtIndex:j];
currentRecord = [self stringValueForCFType:ABRecordCopyValue(currentRecordRef, currentFieldProperty)];
} else {
NSLog(#"self.allKeys has no value at index (%d): %#", j, [allKeys description]);
}
} else {
NSLog(#"self.allContacts has no value at index (%d): %#", i, [allContacts description]);
}
Edit (regarding the comments):
To convert string of property name to its int value, you need to create the following (this probably is not be the correct order that they need to be in, so NSLog them first to see what order they need to be in):
NSString * const ABPropertyID_toString[] = {
#"kABPersonFirstNameProperty",
#"kABPersonLastNameProperty",
#"kABPersonMiddleNameProperty",
#"kABPersonPrefixProperty",
#"kABPersonSuffixProperty",
#"kABPersonNicknameProperty",
#"kABPersonFirstNamePhoneticProperty",
#"kABPersonLastNamePhoneticProperty",
#"kABPersonMiddleNamePhoneticProperty",
#"kABPersonOrganizationProperty",
#"kABPersonJobTitleProperty",
#"kABPersonDepartmentProperty",
#"kABPersonEmailProperty",
#"kABPersonBirthdayProperty",
#"kABPersonNoteProperty",
#"kABPersonCreationDateProperty",
#"kABPersonModificationDateProperty",
#"kABPersonAddressProperty",
// ... etc
};
- (NSString *)ABPropertyIDToString:(ABPropertyID)propertyVal {
return ABPropertyID_toString[propertyVal];
}
- (ABPropertyID)stringToABPropertyID:(NSString *)propertyString {
int retVal;
for(int i=0; i < sizeof(ABPropertyID_toString) - 1; ++i) {
if([(NSString *)ABPropertyID_toString[i] isEqual:propertyString]) {
retVal = i;
break;
}
}
return retVal;
}
Then pass stringToABPropertyID: the value from the array [self.allKeys objectAtIndex:j] and you will be returned an ABPropertyID:
currentFieldProperty = [self stringToABPropertyID:[self.allKeys objectAtIndex:j]];
I'm posting my earlier comment as an answer:
I would especially give thought to the value of currentFieldProperty - because it is taken out of a dictionary, it is an object but the function is supposed to receive an enumerated value. Maybe try
currentFieldProperty = (ABPropertyID)[[self.allKeys objectAtIndex:j] intValue];
Several problems:
ABPropertyID is not an object type. (ABPropertyID)[self.allKeys objectAtIndex:j] is clearly wrong. I'm not sure how it's even possible to be "an array of all properties (each property as string)". What string are you talking about? Where did you get this string from? If you are talking about the string of the name of the property e.g. #"kABPersonEmailProperty" then it would be pretty much impossible to get the value of it from that.
ABPropertyID values like kABPersonEmailProperty are not constants. They are variables, and they only seem to be initialized after you initialize an address book for the first time.
My string comparison keeps returning false and I dont understand why. Even my nslog says the value is correct. Do you know why my comparison keeps returning false even though the strings appear to be the same? If I step through the program type shows SV as its value. I have ensured there are no spaces in this string as well. We get the first two chars of this:
SV2B799E5B-4306-4965-B5DD-944D3970E6B6
NSString *fPath = [path stringByAppendingPathComponent:[directoryContent objectAtIndex:x]];
NSString *fName = [directoryContent objectAtIndex:x];
NSString *type = [fName substringToIndex:2];
NSLog(#"TYPE: %#",type);
if ([type caseInsensitiveCompare:#"SV"])
{
NSData *file = [[NSData alloc] initWithContentsOfFile:fPath];
if (file)
{
[[WebService sharedWebService]saveVolunteer:nil :YES :[directoryContent objectAtIndex:x] :file];
[file release];
}
}
[NSString -caseInsensitiveCompare:] does not return a BOOL, it returns an NSComparisonResult. This is going to be 0 if the strings are equal (in a case insensitive fashion), which is why you're seeing that result.
Invert your result and you'll be set, or to be more correct, check to see if it is == NSOrderedSame.
The method you are calling returns an NSComparisonResult, not a boolean value. It so happens that an NSComparisonResult of equal has the value zero, which is interpreted as false.
caseInsensitiveCompare: returns a NSComparisonResult. Try [type caseInsensitiveCompare:#"SV"] == NSOrderedSame
I'm having a problem with NSRange. Here is my code:
NSRange range = [[[NSHTTPCookie requestHeaderFieldsWithCookies:[[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:[NSURL URLWithString:cookie]]] objectForKey:#"Cookie"] rangeOfString:#"x"];
NSLog(#"%f", range.length);
if (range.length >= 1) {
NSLog(#"Do Something");
} else {
NSLog(#"AUTHING");
}
Console output:
0.000000
Do something
And then the second time I run through the code:
0.000000
AUTHING
What the hell is going on? NSNotFound I think it was does not work and I'm not the only person finding this problem so using it is not a solution.
Thanks for any help.
Cheers
Edit: I tried using NSLog(#"%d", range.length) but it gives incorrect output the first time it runs through, the second time it runs through it is correct. I've tried using NSNotFound thinking that the strange output is due to it being NSNotFound but it didn't trigger
If you want to see if the string was found using -[NSString rangeOfString:], you need to see if NSRange.location == NSNotFound:
if (range.location != NSNotFound) {
// String was found
else {
// String not found
}
As a general comment, debugging is much easier if you split up the nested method calls and do a quick NSLog to see what's going on. (i'm not that good at adhering to that so it's not meant as criticism).
One thing i first noted was the use of "%f" to display the length, try using %i (integer) and you should be able to get the correct length. %f will always display 0.00000.
what url are you using? given that you are pulling the data from the headers, the string "x" may or may not be present in the field. i would suggest NSLog-ing the NSString* object that you pull out of the dictionary and checking to see what's going on. E.g.:NSString *cookie = #"http://www.google.com/";
NSHTTPCookieStorage *store = [NSHTTPCookieStorage sharedHTTPCookieStorage];
NSURL *url = [NSURL URLWithString:cookie];
NSDictionary *header = [NSHTTPCookie requestHeaderFieldsWithCookies: [store cookiesForURL:url]];
NSString *cookieParameter = [header objectForKey:#"Cookie"];
NSLog(#"Cookie param is %#", cookieParameter);
// Test range of "x"
NSRange range = [cookieParameter rangeOfString:#"x"];
NSLog(#"%f", range.length); // will print out 0.00000
NSLog(#"%i", range.length); // will print out correct length (always 1 for "x")
NSLog(#"%i", range.location); // will print out the location of the first instance of "x"
if (range.length >= 1) {
NSLog(#"Do Something");
} else {
NSLog(#"AUTHING");
}
It seems like the code just detects the index of the string "x" from what I can tell, is this the intended result?
I'm downloading a text file and using the information from it to create several objects.
I'm using the following code to achieve this:
NSString *fileContents = [NSString stringWithContentsOfURL: readerView.url
encoding: NSUTF8StringEncoding
error: NULL];
NSArray *lines = [fileContents componentsSeparatedByString:#"\n"];
for(NSString *line in lines)
{
NSArray *params = [line componentsSeparatedByString:#","];
NSString *label1 = [params objectAtIndex:0];
NSString *label2 = [params objectAtIndex:1];
float weight = [[params objectAtIndex:2] floatValue];
int x1 = [[params objectAtIndex:3] intValue];
int y1 = [[params objectAtIndex:4] intValue];
int x2 = [[params objectAtIndex:5] intValue];
int y2 = [[params objectAtIndex:6] intValue];
int type = [[params objectAtIndex:7] intValue];
[graph addComponents:label1:label2 :weight :x1 :y1 :x2 :y2 :type];
}
An example of a line in the text file is like so:
A,B,6.0,270,190,150,190,1
So it's pretty basic. What I wanted to do though was for either the first or last line of the text file, have a URL which would trigger another download for an image. I can't think of what would be the best way to achieve this. In my mind I'm thinking something like this in pseudo code:
If(line = first line)
trigger download
else
go through params.
KennyTM is right, but I would do it the other way around because , is a valid URL character for some schemes and invalid for others, so it's possible (if unlikely) to get a false positive. Parsing the line as a URL will return nil if the line is not a valid URL and then you can parse the line as the formatted data you expect in absence of a URL.
for(NSString *line in lines) {
NSURL* url = [NSURL URLWithString:line];
if (url) {
// trigger download...
} else {
NSArray *params = [line componentsSeparatedByString:#","];
// Do stuff with params
}
}
I would try to check if the line is in the valid params format. If not, try to parse as URL.
Assuming the URL doesn't contain exactly 7 commas,
for(NSString *line in lines) {
NSArray *params = [line componentsSeparatedByString:#","];
if ([params count] == 8) {
// go through params
} else {
NSURL* url = [NSURL URLWithString:line];
if (url) {
// trigger download...
}
}
}
This way the URL can be placed anywhere in the file.
I cant seem to find what would be the problem here...
NSArray *oneMove;
oneMove = [[bestMoves objectAtIndex:i] componentsSeparatedByString:#","];
int from, to;
int temp = [[oneMove objectAtIndex:0] intValue];
from = [temp intValue]/100; //"Invalid receiver type int"
to = [temp intValue]%100; //"Invalid receiver type int"
NSLog(#"%d, %d", from, to);
The thing is: it works and 'from' and 'to' get the right values but i get warnings at the indicated lines...
anyone knows why and how to fix that? (dont like them warnings when compiling ;) )
temp is already int value, no NSNumber. So you cannot send an [temp intValue] message to it.
Just use
from = temp / 100;
to = temp % 100;
Edit: Here is code that proves it works:
NSArray *bestMoves = [NSArray arrayWithObject:#"499,340,124"]; // Example data
NSArray *oneMove = [[bestMoves objectAtIndex:0] componentsSeparatedByString:#","];
int from, to;
int temp = [[oneMove objectAtIndex:0] intValue];
from = temp/100; // Code change
to = temp%100; // Code change
NSLog(#"%d, %d", from, to);
Output is as expected 4, 99.