creating default vars (objects) in objective c - ios

dumb question: lets say I'm assigning a var in a conditional statement. I don't know if the condition will be satisfied and i still want the var to be defined.. whats the correct way of writing this
example:
NSDecimalNumber *number = [[NSDecimalNumber alloc]init]; // this is pointless right?
if(x == z){
number = [whatevernum1 decimalNumberByMultiplyingBy: whatevernum2];
} else {
number = [whatevernum2 decimalNumberByDividingBy: whatevernum3];
}
// do something with number variable.

There is no need to initialize number since it will be set. Just do this:
NSDecimalNumber *number;
if(x == z){
number = [whatevernum1 decimalNumberByMultiplying: whatevernum2];
} else {
number = [whatevernum2 decimalNumberByDividing: whatevernum3];
}
// do something with number variable.
In your case number will be assigned a value one way or another. But you might have a situation like this:
if (someCondition) {
// set number to value A
} else if (anotherCondition) {
// set number to value B
}
Here, it is possible that neither condition is met. In this case you need to deal with this properly by initializing number to nil.
NSDecimalNumber *number = nil;
if (someCondition) {
// set number to value A
} else if (anotherCondition) {
// set number to value B
}
if (number) {
// process result
}

You need to declare the variable but not assign it, like this:
NSDecimalNumber *number;
if(x == z){
number = [whatevernum1 decimalNumberByMultiplying: whatevernum2];
} else {
number = [whatevernum2 decimalNumberByDividing: whatevernum3];
}
This tells the compiler that you want to use a variable named number, but don't have a value for it yet. In some cases, you may find it convenient to initialise the variable to nil rather than leaving it as a null pointer.

Normally, as others have pointed out, you would either not initialise (if you can guarantee that you will set a value, eg through an if/else pair), or you would initialise to nil.
In this simple case, a ternary statement would make your code much clearer:
NSDecimalNumber *number = x == z ? [whatevernum1 decimalNumberByMultiplyingBy:whatevernum2] : [whatevernum2 decimalNumberByDividingBy:whatevernum3];

Related

What is the Use of "NSNumber numberWithInt" in Xcode

i'm retrieving data from server - where the NS Number used contains BOOL value in database format. but when i try to use TRUE or FALSE , it doest allow to do.
- i'm a Beginner of Xcode.
for (unsigned int i =0; i<studentDashBoardDetails.count; i++) {
// Early CheckOut Days
if ([[[ studentDashBoardDetails objectAtIndex:i]objectForKey:#"dayType"]isEqualToString: #"Working"]&&[[[studentDashBoardDetails objectAtIndex:i]objectForKey:#"isAttended"]isEqualToNumber:[NSNumber numberWithInt:1]]&&[[[studentDashBoardDetails objectAtIndex:i]objectForKey:#"timeSpent"]isLessThan:#"08.00.00"])
{
NSLog(#" Early Check out on %#",[[studentDashBoardDetails objectAtIndex:i]objectForKey:#"attendanceDate"]);
NSNumber numberWithInt returns the signed integer for the current value, to access bool values you can use NSNumber numberWithBool method, it creates an object and returns NSNumber which can be treated as a bool.
I hope it will help you in achieving proper way on how to solve your problem
While saving save as NSNumber like this
NSNumber *isAttended = [[studentDashBoardDetails objectAtIndex:i]objectForKey:#"isAttended"];
and while reading it do your condition like this
if (isAttended.boolValue){
//true
}else{
//false
}
in your case you have to do like this
if ([[[ studentDashBoardDetails objectAtIndex:i]objectForKey:#"dayType"]isEqualToString: #"Working"] && isAttended.boolValue &&[[[studentDashBoardDetails objectAtIndex:i]objectForKey:#"timeSpent"]isLessThan:#"08.00.00"])
{
NSLog(#" Early Check out on %#",[[studentDashBoardDetails objectAtIndex:i]objectForKey:#"attendanceDate"]);
}

Expected method to read array element not found on object of type NSDictionary*

I know there's a lot of questions like this around, but I think my situation's a tad different.
int i = 0;
while (_data[#"VerticalState%i", i] != nil) {
// do things
i++;
}
For example, one 'level' that has 3 VerticalState properties will be implemented as such: VerticalState0, VerticalState1, VerticalState2.
I want to read in those values using that while loop condition above, and it should stop when i = 3. How can I make the idea of that code above work (with some other configuration obviously). FYI, _data is an NSDictionary* instance variable, already loaded with the plist information.
You appear to want to create a dictionary key from a string format. You need to use NSString stringWithFormat:.
while (_data[[NSString stringWithFormat:#"VerticalState%i", i]] != nil) {
Though it would be better to write the loop like this:
int i = 0;
while (1) {
NSString *key = [NSString stringWithFormat:#"VerticalState%i", i];
id value = _dict[key];
if (value) {
// do things
i++;
} else {
break;
}
}

Compare two hour strings Objective C

I have an string with an hour in it, for example "15:15", and an array of other hours in strings ex: #["15:00","16:00","17:00"] I should compare the single string with the array ones in order to get the ETA in a bus station, I tried this code but it keeps iterating and gives me the last greater value in the array, not the first greater value as I need.
int i = 0;
horaArribada = [[[objects objectAtIndex:0]objectForKey:#"Horaris"]objectAtIndex:i];
while ([hora compare:horaArribada]) {
i++;
if (i >= [[[objects objectAtIndex:0]objectForKey:#"Horaris"]count]) {
break;
}else{
horaArribada = [[[objects objectAtIndex:0]objectForKey:#"Horaris"]objectAtIndex:i];
}
}
self.tfHoraArribada.text = horaArribada;
}
}
Where objects is a query from Parse and hora the single string with an hour in it.
You appear to be doing a lot of extra work to iterate over your array. Instead, try a different format for your loop:
for (NSString *horaArribada in [[objects objectAtIndex:0] objectForKey:#"Horaris"]) {
if ([hora compare:horaArribada] == NSOrderedAscending) {
self.tfHoraArribada.text = horaArribada;
break;
}
}
This assumes that your Horaris array is already sorted such from smallest to largest. Also, the logic will not work for the midnight rollover, so you'll probably want to account for that.

Compare 2 Objects in Objective-C

In my application, I want to compare 2 core data instances of the entity "Workout". I want to check if the 2 objects have identical attribute values for all of their attributes. Essentially if the two objects are the same minus the relationship, whosWorkout. Is there any way to do this without manually checking every single attribute? I know I could do:
if(object1.intAttr == object2.intAttr){
NSLog(#"This attribute is the same");
}
else{
return;
}
repeat with different attributes...
Is there any core data method to make this a bit less tedious?
First I would create an isEqual method in the Workout subclass like this...
-(BOOL)isEqualToWorkout:(Workout*)otherWorkout
{
return [self.attribute1 isEqual:otherWorkout.attribute1]
&& [self.attribute2 isEqual:otherWorkout.attribute2]
&& [self.attribute3 isEqual:otherWorkout.attribute3]
&& [self.attribute4 isEqual:otherWorkout.attribute4]
...;
}
Then whenever you want to compare to Workout objects just use...
BOOL equal = [workout1 isEqualToWorkout:workout2];
You can iterate through the attributes by name.
for (NSString *attribute in object.entity.attributesByName) {
if ([[object valueForKey:attribute] intValue] !=
[[object2 valueForKey:attribute] intValue]) {
return NO;
}
}
return YES;
This assumes all integer attributes. You could do a switch statement to check for the class with the class method and deal with different data types as well.
If you need to compare whether one object represents a greater or lesser value than another object, you can’t use the standard C comparison operators > and <. Instead, the basic Foundation types, like NSNumber, NSString and NSDate, provide a compare: method:
if ([someDate compare:anotherDate] == NSOrderedAscending) {
// someDate is earlier than anotherDate
}
I ended up doing the following:
-(BOOL)areEqual:(Workout *)firstWorkout secondWorkout:(Workout *)secondWorkout{
NSArray *allAttributeKeys = [[[firstWorkout entity] attributesByName] allKeys];
if([[firstWorkout entity] isEqual:[secondWorkout entity]]
&& [[firstWorkout committedValuesForKeys:allAttributeKeys] isEqual:[secondWorkout committedValuesForKeys:allAttributeKeys]]) {
return YES;
}
else{
return NO;
}
}

Case insensitive compare against bunch of strings

What would be the best method to compare an NSString to a bunch of other strings case insensitive? If it is one of the strings then the method should return YES, otherwise NO.
Here's a little helper function:
BOOL isContainedIn(NSArray* bunchOfStrings, NSString* stringToCheck)
{
for (NSString* string in bunchOfStrings) {
if ([string caseInsensitiveCompare:stringToCheck] == NSOrderedSame)
return YES;
}
return NO;
}
Of course this could be greatly optimized for different use cases.
If, for example, you make a lot of checks against a constant bunchOfStrings you could use an NSSet to hold lower case versions of the strings and use containsObject::
BOOL isContainedIn(NSSet* bunchOfLowercaseStrings, NSString* stringToCheck)
{
return [bunchOfLowercaseStrings containsObject:[stringToCheck lowercaseString]];
}
Just to add a few additions to Nikolai's answer:
NSOrderedSame is defined as 0
typedef NS_ENUM(NSInteger, NSComparisonResult) {NSOrderedAscending = -1L, NSOrderedSame, NSOrderedDescending};
So if you call caseInsensitiveCompare: on a nil object you would get nil. Then you compare nil with NSOrderSame (which is 0) you would get a match which of course is wrong.
Also you will have to check if parameter passed to caseInsensitiveCompare: has to be not nil. From the documentation:
This value must not be nil. If this value is nil, the behavior is
undefined and may change in future versions of OS X.

Resources