Int decimal count in iPhone - iphone

I need to know whatever an int64_t has decimals, and how many. This should be placed in if-else-statement. I tried this code, but it causes the app to crash.
NSNumber *numValue = [NSNumber numberWithInt:testAnswer];
NSString *string = [numValue stringValue];
NSArray *stringComps = [string componentsSeparatedByString:#"."];
int64_t numberOfDecimalPlaces = [[stringComps objectAtIndex:1] length];
if (numberOfDecimalPlaces == 0) {
[self doSomething];
} else {
[self doSomethingElse];
}

Your question doesn't make a lot of sense; you are creating the NSNumber object from an int so it will never have decimal places, as an int cannot store them. The reason your code is crashing is that it assumes that the array of components is always at least 2 elements long (as you use objectAtIndex:1).
This is better, though still not that good:
NSString *answer = ...; // From somewhere
NSArray *stringComps = [answer componentsSeparatedByString:#"."];
if ([stringComps count] == 0) {
[self doSomething];
} else if [stringComps count] == 1) {
[self doSomethingElse];
} else {
// Error! More than one period entered
}
This still isn't a very good test as it only tests if a period (.) has been entered, not a valid number.

Related

How to use compare on a version number where theres less parts in one number in Objective-C?

I've found the following code at http://snipplr.com/view/2771
Which is pretty good, almost exactly what I was looking for, but if I use the values #"1.4.5", #"10.4" it produces the wrong result, saying that the first number is lower.
Arghhhh Late night coding, sorry I read 10.4 as 1.4 :(
I'm unsure why compare is having an issue and what the problem is ?
/*
* compareVersions(#"10.4", #"10.3"); //
returns NSOrderedDescending (1) - aka first number is higher
* compareVersions(#"10.5", #"10.5.0"); //
returns NSOrderedSame (0)
* compareVersions(#"10.4 Build 8L127", #"10.4 Build 8P135"); //
returns NSOrderedAscending (-1) - aka first number is lower
*/
NSComparisonResult compareVersions(NSString* leftVersion, NSString* rightVersion)
{
int i;
// Break version into fields (separated by '.')
NSMutableArray *leftFields = [[NSMutableArray alloc] initWithArray:[leftVersion componentsSeparatedByString:#"."]];
NSMutableArray *rightFields = [[NSMutableArray alloc] initWithArray:[rightVersion componentsSeparatedByString:#"."]];
// Implict ".0" in case version doesn't have the same number of '.'
if ([leftFields count] < [rightFields count]) {
while ([leftFields count] != [rightFields count]) {
[leftFields addObject:#"0"];
}
} else if ([leftFields count] > [rightFields count]) {
while ([leftFields count] != [rightFields count]) {
[rightFields addObject:#"0"];
}
}
.
// Do a numeric comparison on each field
for(i = 0; i < [leftFields count]; i++) {
NSComparisonResult result = [[leftFields objectAtIndex:i] compare:[rightFields objectAtIndex:i] options:NSNumericSearch];
if (result != NSOrderedSame) {
[leftFields release];
[rightFields release];
return result;
}
}
[leftFields release];
[rightFields release];
return NSOrderedSame;
}
[I posted this earlier today, but it was not selected as the answer, and it may be more appropriate to your problem. There are other techniques, you can look here and here for other solutions.]
What I do is take that string and break it into components:
NSArray *array = [myVersion componentsSeparatedByCharactersInSet:#"."];
NSInteger value = 0;
NSInteger multiplier = 1000000;
for(NSString *n in array) {
value += [n integerValue] * multiplier;
multiplier /= 100;
}
What this does is give you a normalized value you can use for comparison, and will generally compare releases that have different "depths", ie 1.5 and 1.5.2.
It breaks if you have more than 100 point releases (ie any number is > 100) and also will declare 1.5.0 == 1.5. That said, its short, sweet, and simple to use.
EDIT: if you use the NSString 'compare:options:' method, make sure you have your string well groomed:
s1 = #"1.";
s2 = #"1";
NSLog(#"Compare %# to %# result %d", s1, s2, (int)[s1 compare:s2 options:NSNumericSearch]);
s1 = #"20.20.0";
s2 = #"20.20";
NSLog(#"Compare %# to %# result %d", s1, s2, (int)[s1 compare:s2 options:NSNumericSearch]);
2012-09-06 11:26:24.793 xxx[59804:f803] Compare 1. to 1 result 1
2012-09-06 11:26:24.794 xxx[59804:f803] Compare 20.20.0 to 20.20 result 1
The Sparkle framework for Mac is open source, and it has some neat version checking code you can have a look at: https://github.com/andymatuschak/Sparkle/blob/master/SUStandardVersionComparator.m
so you want to compare 10.5 to 1.4.6 such that 10.5 is viewed as 0.10.5
if this is the case, you need to add "0" array items to the left side of your separated version number
NSComparisonResult compareVersions(NSString* leftVersion, NSString* rightVersion)
{
int i;
// Break version into fields (separated by '.')
NSMutableArray *leftFields = [[NSMutableArray alloc] initWithArray:[leftVersion componentsSeparatedByString:#"."]];
NSMutableArray *rightFields = [[NSMutableArray alloc] initWithArray:[rightVersion componentsSeparatedByString:#"."]];
// Implict "0" in case version doesn't have the same number of '.'
if ([leftFields count] < [rightFields count]) {
while ([leftFields count] != [rightFields count]) {
[leftFields insertObject:#"0" atIndex:0];
}
} else if ([leftFields count] > [rightFields count]) {
while ([leftFields count] != [rightFields count]) {
[rightFields insertObject:#"0" atIndex:0];
}
}
I'm not 100% sure what you're asking, but if you're looking to sort numbers regardless of how many periods "." are in the number you can use an NSSortDescriptor on a dictionary of OS versions:
NSArray *originalArray = [NSArray arrayWithObjects:
[NSDictionary dictionaryWithObject:#"10.4.5" forKey:#"version"],
[NSDictionary dictionaryWithObject:#"10.5.6" forKey:#"version"],
[NSDictionary dictionaryWithObject:#"10.6.8" forKey:#"version"],
[NSDictionary dictionaryWithObject:#"10.8" forKey:#"version"],
[NSDictionary dictionaryWithObject:#"10.7.1" forKey:#"version"],
[NSDictionary dictionaryWithObject:#"10.8.2" forKey:#"version"],
nil];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:#"version" ascending:true];
NSArray *sortedArray = [originalArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
NSLog(#"Lowest to highest: %#", sortedArray);
NSLog(#"Highest OS version: %#",[[sortedArray objectAtIndex:[sortedArray indexOfObject:[sortedArray lastObject]]] objectForKey:#"version"]);
My sense would be that the first numeral group is always the most significant, so 10.anything is bigger than 9.anything.anything. If I'm right about that, then the solution is to replace the dots with zeros and pad the shorter string on the right-hand side with zeros to match the length of the longer string:
e.g.
9.4 ---> 90400 (padded on the right with 00)
8.6.7 ---> 80607
What's nice about this is, that if I'm wrong about the requirement, the algorithm can be readily fixed by padding the shorter string on the right.
- (NSComparisonResult)compareVersion:(NSString *)vA withVersion:(NSString *)vB {
NSString *vAPadded = [vA stringByReplacingOccurrencesOfString:#"." withString:#"0"];
NSString *vBPadded = [vB stringByReplacingOccurrencesOfString:#"." withString:#"0"];
while (vAPadded.length < vBPadded.length)
vAPadded = [vAPadded stringByAppendingString:#"0"];
while (vBPadded.length < vAPadded.length)
vBPadded = [vBPadded stringByAppendingString:#"0"];
return [vAPadded intValue] - [vBPadded intValue];
}
If I've got the requirement backwards on significant digits, change the pads like this:
vAPadded = [#"0" stringByAppendingString:vAPadded];
Why don't use NSString compare:options:NSNumericSearch
NSString *sysVer = [[UIDevice currentDevice] systemVersion];
NSLog(#"%#,%d,%d,%d", sysVer, [sysVer compare:#"1.0" options: NSNumericSearch], [sysVer compare:#"6.0" options: NSNumericSearch],[sysVer compare:#"10.0" options: NSNumericSearch]);
if ([sysVer compare:#"6.0" options: NSNumericSearch]>=NSOrderedSame) {
NSLog(#"ios 6");
}
You can use my Version class that helps you to parse your version strings into Version objects for easy compare. It supports 4 field version numbers like major.minor.release.build, all fields are optional. Also, it has a compare method for comapring two version objects.
https://github.com/polatolu/version-ios
it's simple with VersionComparator Class
https://github.com/danhanly/VersionComparator
BOOL greater = [VersionComparator isVersion:#"2.0.0" greaterThanVersion:#"1.1.0"];
As answered in this post; Compare version numbers in Objective-C
Check out my NSString category that implements easy version checking on github; https://github.com/stijnster/NSString-compareToVersion
[#"1.2.2.4" compareToVersion:#"1.2.2.5"];
This will return a NSComparisonResult which is more accurate then using;
[#"1.2.2" compare:#"1.2.2.5" options:NSNumericSearch]
Helpers are also added;
[#"1.2.2.4" isOlderThanVersion:#"1.2.2.5"];
[#"1.2.2.4" isNewerThanVersion:#"1.2.2.5"];
[#"1.2.2.4" isEqualToVersion:#"1.2.2.5"];
[#"1.2.2.4" isEqualOrOlderThanVersion:#"1.2.2.5"];
[#"1.2.2.4" isEqualOrNewerThanVersion:#"1.2.2.5"];

How to sort an array with alphanumeric values?

I have an array which contains strings like frame_10#3x.png , frame_5#3x.png,frame_19#3x.png etc.
So I want to sort this array according to the number after the underscore i.e. the correct sequence will be frame_5#3x.png,frame_10#3x.png,frame_19#3x.png.
I tried to use the following method but no result:
NSInteger firstNumSort(id str1, id str2, void *context) {
int num1 = [str1 integerValue];
int num2 = [str2 integerValue];
if (num1 < num2)
return NSOrderedAscending;
else if (num1 > num2)
return NSOrderedDescending;
return NSOrderedSame;
}
Please suggest how to do this sorting for array.
NSArray *sry_img = [[NSArray alloc] initWithObjects:#"frame_18#3x.png",#"frame_17#3x.png",#"frame_1222#3x.png",#"frame_10#3x.png",#"frame_3#3x.png",#"frame_4#3x.png",#"frame_4#3x.png",#"frame_1#3x.png",#"frame_4#3x.png",#"frame_4#3x.png",nil];
NSArray *sortedStrings = [sry_img sortedArrayUsingSelector:#selector(localizedStandardCompare:)];
NSLog(#"%#",sortedStrings);
Enjy .......
But
localizedStandardCompare:, added in 10.6, should be used whenever file names or other strings are presented in lists and tables where Finder-like sorting is appropriate. The exact behavior of this method may be tweaked in future releases, and will be different under different localizations, so clients should not depend on the exact sorting order of the strings.
you want to do something like:
NSArray *components1 = [str1 componentsSeparatedByString:#"_"];
NSArray *components2 = [str2 componentsSeparatedByString:#"_"];
NSString *number1String = [components1 objectAtIndex:([components1 count] - 1])];
NSString *number2String = [components2 objectAtIndex:([components2 count] - 1])];
return [number1String compare:number2String];
I am not sure if my solution is the best possible approach but it can solve your problem for the time being :) .
1) First I have written a function to get the numbers before # character in your string and then I implemented simple SELECTION SORT algo to sort the array using this functions.
- (NSString*)getSubStringForString:(NSString*)value {
// First we will cut the frame_ string
NSMutableString *trimmedString = [NSMutableString stringWithString:[value substringWithRange:NSMakeRange(6, [value length]-6)]];
// New String to contain the numbers
NSMutableString *newString = [[NSMutableString alloc] init];
for (int i = 0; i < [trimmedString length] ; i++) {
NSString *singleChar = [trimmedString substringWithRange:NSMakeRange(i, 1)];
if (![singleChar isEqualToString:#"#"]) {
[newString appendString:singleChar];
} else {
break;
}
}
return newString;
}
This is the selection Implementation of the algo for sorting. The main logic is in the for loop. You can copy the code in viewDidLoad method to test.
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"frame_10#3x.png",#"frame_5#3x.png",
#"frame_3#3x.png", #"frame_19#3x.png",
nil];
NSLog(#"Values before Sort: %#", array);
int iPos;
int iMin;
for (iPos = 0; iPos < [array count]; iPos++)
{
iMin = iPos;
for (int i = iPos+1; i < [array count]; i++)
{
if ([[self getSubStringForString:[array objectAtIndex:i]] intValue] >
[[self getSubStringForString:[array objectAtIndex:iMin]] intValue]) {
iMin = i;
}
}
if ( iMin != iPos )
{
NSString *tempValue = [array objectAtIndex:iPos];
[array replaceObjectAtIndex:iPos withObject:[array objectAtIndex:iMin]];
[array replaceObjectAtIndex:iMin withObject:tempValue];
}
}
NSLog(#"Sorted Values: %#", array);
I hope that it can atleast keep you going. :)
You can try this-
NSString *str1 = [[[[str1 componentsSeparatedByString:#"frame_"] objectAtIndex:1] componentsSeparatedByString:#"#3x.png"] objectAtIndex:0];
int num1 = [str1 integerValue];

ABRecordCopyValue and ABPropertyID crash

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.

Change UILabel in loop

I want to change the UILabel after 2 sec in a loop.
But current code change it to last value after loop finished.
- (IBAction) start:(id)sender{
for (int i=0; i<3; i++) {
NSString *tempStr = [[NSString alloc] initWithFormat:#"%s", #" "];
int randomNumber = 1+ arc4random() %(3);
if (randomNumber == 1) {
tempStr = #"Red";
}else if (randomNumber == 2) {
tempStr = #"Blue";
} else {
tempStr = #"Green";
}
NSLog(#"log: %# ", tempStr);
labelsText.text = tempStr;
[tempStr release];
sleep(2);
}
}
Your code updates label to last value only as your function blocks main thread so UI cannot get updated. To solve that problem move your updating code to separate function and call it using performSelector:withObject:afterDelay: method. (or schedule calls using NSTimer)
Possible solution (you will also need to handle the case when user taps your button several times in a row, but that should not be too difficult):
- (IBAction) start:(id)sender{
[self updateLabel];
}
- (void) updateLabel{
static const NSString* allStrings[] = {#"Red", #"Blue", #"Green"};
static int count = 0;
int randomNumber = arc4random()%3;
NSString *tempStr = allStrings[randomNumber];
NSLog(#"log: %# ", tempStr);
labelsText.text = tempStr;
++count;
if (count)
[self performSelector:#selector(updateLabel) withObject:nil afterDelay:2.0];
}
- (IBAction) start:(id)sender{
for (int i=0; i<3; i++) {
int randomNumber = 1+ arc4random() %(3);
NSString *tempStr = #"";
if (randomNumber == 1) {
tempStr = #"Red";
}else if (randomNumber == 2) {
tempStr = #"Blue";
} else {
tempStr = #"Green";
}
[labelsText performSelector:#selector(setText:) withObject:tempStr afterDelay:i * 2]
NSLog(#"log: %# ", tempStr);
}
}
Don't use sleep() to perform actions after a delay, it blocks the whole thread. Use performSelector:withObject:afterDelay: instead. As you are probably running this on the main thread, sleep() will block any UI updates until after the whole loop has run, so the only thing you see is the last update. As a general rule of thumb, assume that the UI doesn't ever get updated until after the app has finished executing your method.
You shouldn't use %s as the format specifier for an NSString, that's the format specifier for a C string. You should use %# instead. In fact, if all you are doing is initialising the string with an NSString literal, there's no need to use initWithFormat at all, you can just use the literal itself.
You've also got big memory problems. At the beginning of the loop, you allocate memory for an instance of NSString that is a single space. You then overwrite the pointer to this memory when you assign to tempStr again, meaning you leak the original allocation of memory. Build and Analyze will find problems like this for you. Then you release tempStr, but as the second assignment to this pointer variable was to an autoreleased NSString, the instance will be released one time too many when the autorelease pool gets drained, which will probably manifest itself as a crash that's impossible to debug a little later in the app.
I'd do something like this:
- (void)showRandomColourAfterDelay {
static NSUInteger count = 0;
switch (arc4random()%3) {
case 0:
labelsText.text = #"Red";
case 1:
labelsText.text = #"Blue";
case 2:
labelsText.text = #"Green";
}
count++;
if (count >= 3) return;
[self performSelector:#selector(showRandomColourAfterDelay) withObject:nil afterDelay:3];
}
In fact, I'd probable use an NSArray to hold the colour strings, but that would involve changes outside of a single method, so I've stuck with your hard-coding approach.

Why doesn't this for loop execute?

I have a picker view controller to select a chemical source and possibly a concentration. If the source doesn't have concentrations, it just presents a single picker. It gets populated by an NSDictionary with source type names as keys and a custom model object I made called Chemical that has four properties, two NSString, one float and one BOOL.
When I trigger this with dictionary that has 2 components, I want to extract the four values from the Chemical that is represented. Note that I populate the picker with values from the first two properties, but not the float or BOOL. I run through the array for the key that's selected in the first component and check the string from the second component against the chemConcentration property from each of the Chemicals in the key/value array. When the chemConcentration matches, I know I have the right Chemical and I can get its properties to send back.
Whew!
The problem is that even though I know I get to the for loop, it seems to get skipped. The NSLog right before it prints, but the one inside doesn't. sourceConstant and sourceIsLiquid stay 0.0 and NO
- (IBAction)selectedSourceButton {
NSLog(#"selectedSourceButton pressed");
NSInteger sourceRow = [picker selectedRowInComponent:kSourceComponent];
NSString *selectedSource = [self.sources objectAtIndex:sourceRow];
NSArray *selectedChemicalGroup = [dictionaryOfSources objectForKey:selectedSource];
NSInteger concentrationRow = [picker selectedRowInComponent:kConcentrationComponent];
NSString *selectedConcentration = [[NSString alloc] init];
float selectedConstant = 0.0;
BOOL selectedIsLiquid = NO;
if (numberOfComponents == 2) {
NSLog(#"numberOfComponents = 2 if/then chosen"); // <-- This prints.
selectedConcentration = [self.concentrations objectAtIndex:concentrationRow];
NSLog(#"begin selectedConcentration for loop. Number of loops = %d", [selectedChemicalGroup count]); // <-- And so does this.
for (int i; i<[selectedChemicalGroup count]; i++) { // <-- But this doesn't seem to fire!
NSLog(#"selectedConcentration = %#, from selectedChemicalGroup = %#", selectedConcentration, [[selectedChemicalGroup objectAtIndex:i] chemConcentration]); // <-- Because this doesn't print.
if ([selectedConcentration isEqualToString:[[selectedChemicalGroup objectAtIndex:i] chemConcentration]]) {
selectedConstant = [[selectedChemicalGroup objectAtIndex:i] chemConstant];
selectedIsLiquid = [[selectedChemicalGroup objectAtIndex:i] chemIsLiquid];
}
}
}
else {
selectedConcentration = #"";
selectedConstant = [[selectedChemicalGroup objectAtIndex:0] chemConstant];
selectedIsLiquid = [[selectedChemicalGroup objectAtIndex:0] chemIsLiquid];
}
NSLog(#"selectedSourceButton source to return = %#, concentration = %#, sourceConstant = %1.7f, isLiquid = %d", selectedSource, selectedConcentration, selectedConstant, selectedIsLiquid);
if ([self.delegate respondsToSelector:#selector (sourcePickerViewController:didSelectSource:andConcentration:andConstant:andIsLiquid:)]) {
[self.delegate sourcePickerViewController:self didSelectSource:selectedSource andConcentration:selectedConcentration andConstant:selectedConstant andIsLiquid:selectedIsLiquid];
}
}
You need to initialize your variable i: for (int i = 0; ...
But there's a better way to do this, using "fast enumeration":
for (MyChemicalGroupClass *group in selectedChemicalGroup) {
if ([selectedConcentration isEqualToString:[group chemConcentration]]) {
...
}
}
Initialize loop count i
for (int i = 0; i<[selectedChemicalGroup count]; i++)
Do the following and you will understand why:
int i;
NSLog(#"%d", i);