Objective-C: NSArray of UISwitches - objective-c

Ok so I;m building an interface to allow admins controlls over certain rules which are controlled using UISwitches (a lot of them)
so I've declared an array of switches
NSMutableArray *cameraSwitches = [[NSMutableArray alloc] initWithObjects:
loc0CamProfileSwitch, loc1CamProfileSwitch, loc2CamProfileSwitch,
loc3CamProfileSwitch, loc4CamProfileSwitch, loc5CamProfileSwitch,
loc6CamProfileSwitch, loc7CamProfileSwitch, loc8CamProfileSwitch, nil];
where each object inside the Array is a UISwitch,
and then I'm looping through a diff array checking for initial values of these switches
for (NSUInteger i = 0; i < [camP count]; i++) {
if ([camP objectAtIndex:i] != 0) {
//UISwitch *csw = [cameraSwitches objectAtIndex:i];
//[csw setOn:YES];
[[cameraSwitches objectAtIndex:i] setOn:YES];
else { [loc7CamProfileSwitch setOn:NO]; }
}
But everything I'm trying is giving me an error at runtime, throwing an exception
'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
using break points: I realize theres something wrong with this line
[[cameraSwitches objectAtIndex:i] setOn:YES]; - or with how i initiated the array any help is very very appreciated

cameraSwitches is correctly instantiated. that's why you get an exception raised when you try to reach index 0.
But, did you checked that loc0CamProfileSwitch (index 0) is non nil?

Most likely, cameraSwitches is getting deallocated after it's instantiated. This could happen if you create it in a different method than when you're calling objectAtIndex and you're not setting it up as an iVar or #property (strong).
If that doesn't resolve the issue, put a breakpoint on [[cameraSwitches objectAtIndex:i] setOn:YES] and type po cameraSwitches in the debug console.

Related

Invalid Selector on doubleValue

A bit new to Objective-C, so please bear with me.
Firstly, I'm using the FMDB library for SQLite management.
I'm populating an NSMutableDictionary using the following method:
//....
while([effectivenessResults next]) //this loops through the results of a query (verified that this works)
{
NSMutableArray *dFactors = [[NSMutableArray alloc]init];
if([resultDict objectForKey:[effectivenessResults stringForColumn:#"tName"]])
{
dFactors = [resultDict objectForKey:[effectivenessResults stringForColumn:#"tName"]];
}
NSNumber *effectivenessValToAdd = [NSNumber numberWithDouble:[effectivenessResults doubleForColumn:#"dFactor"]/100];
[dFactors addObject:[NSMutableString stringWithFormat:#"%#",effectivenessValToAdd]];
[resultDict setObject:dFactors forKey:[effectivenessResults stringForColumn:#"tName"]];
}
I'm returning the array properly (I have verified this). Then, I am accessing this NSMutableDictionary elsewhere, using the follwing method:
for(id type in tEffect) //tEffect is the NSMutableDictionary, returned from the previous code (there known as resultDict)
{
effectivenessString = [self getEffectivenessString:[tEffect objectForKey:type]];
tInfo = [NSMutableString stringWithFormat:#"%#", [tInfo stringByAppendingFormat:#"%#: %#\n", type, effectivenessString]];
}
which calls the following two methods:
-(NSMutableString *)getEffectivenessString:(NSNumber *) numberPassedIn
{
double dFactor = [numberPassedIn doubleValue];
//adds the above value to a string, this will not affect anything
}
and
-(NSNumber *) listProduct: (NSMutableArray *)listOfValues //calculates the product of an NSMutableArray of numbers
{
NSNumber *product=[NSNumber numberWithDouble:1.0];
for(int i = 0; i < [listOfValues count]; i++)
{
NSNumber *newVal = [listOfValues objectAtIndex:i];
product = [NSNumber numberWithDouble:[product doubleValue] * [newVal doubleValue]];
}
return product;
}
So, when I call these methods, I am getting the following error:
2013-08-04 13:52:04.514 effectCalculator[45573:c07] -[__NSArrayM doubleValue]:
unrecognized selector sent to instance 0x8c19e00
2013-08-04 13:52:04.521 effectCalculator[45573:c07] *** Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '-[__NSArrayM doubleValue]: unrecognized
selector sent to instance 0x8c19e00'
Important to note: This error occurs on the retrieval, NOT the populating of the NSMutableDictionary. This means the population of this dictionary not the an issue, but it might have something to do with why it's having trouble retrieving the data.
So what might cause this error?
Your code is pretty difficult to follow. In future please post a minimal sample which compiles, or at least is a single block of understandable code.
Having said that, I believe your issue is with this bit:
for(id type in tEffect) //tEffect is the NSMutableDictionary, returned from the previous code (there known as resultDict)
{
effectivenessString = [self getEffectivenessString:[tEffect objectForKey:type]];
what does resultDict contain?
[resultDict setObject:dFactors ...
but dFactors is an NSMutableArray. Well getEffectivenessString expects a NSNumber, not a NSMutableArray. So it complains. Also I think you intended for the method to take a string, not a number, although I don't see why you're not casting as you load them (instead of as you use them).
Since Objective C doesn't support strongly-typed arrays or dictionaries, your best bet to defend against this in the future is to name your variables more logically. It should stand out when you try to call a method which expects a number with an array instead.

replaceObjectAtIndex:withObject does not work

I am trying to assign objects in an NSMutableArray using this code
- (IBAction)variablePressed:(UIButton *)sender {
NSString *variable = [sender currentTitle];
if (!_variableToBePassedIntoTheDictionary) _variableToBePassedIntoTheDictionary = [[NSMutableArray alloc] init];
[_variableToBePassedIntoTheDictionary replaceObjectAtIndex:0 withObject:variable];}
but when I run this program the program breaks at the last line, since I have set the debugger to show warnings if a Exception is raised. Running the program without breakpoints, the program gives SIGARBT and crashes. I then assign these values to a dictionary which would be passed to the Model for further calculations.
- (IBAction)testVariableValues:(id)sender {
if (!_variablesAssignedInADictionary) _variablesAssignedInADictionary = [[NSMutableDictionary alloc] init];
[_variablesAssignedInADictionary setObject:_digitToBePassedIntoTheVariable forKey:_variableToBePassedIntoTheDictionary];
NSLog(#"%#", _variablesAssignedInADictionary);}
P.S. I am new in Objective C, can anybody please explain when do we use
#synthesize someProperty;
vs
#synthesize someProperty = _someProperty;
Thank You!
The first time the method is called you create the NSMutableArray and then attempt to replace an object which is not there. The reference says:
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject
The index of the object to be replaced. This value must not exceed
the bounds of the array. Important Raises an NSRangeException if
index is beyond the end of the array.
And 0 will exceed the bounds of an empty array.
Try this instead:
- (IBAction)variablePressed:(UIButton *)sender
{
NSString *variable = [sender currentTitle];
if (_variableToBePassedIntoTheDictionary == nil)
{
_variableToBePassedIntoTheDictionary = [[NSMutableArray alloc] init];
[_variableToBePassedIntoTheDictionary addObject:variable];
}
else
{
[_variableToBePassedIntoTheDictionary replaceObjectAtIndex:0 withObject:variable];
}
}
Taken from the docs :
The index of the object to be replaced. This value must not exceed the
bounds of the array.
As I see from your code your array is initialized and there is no object at index 0. hence you try to replace an object at an index which is out of bounds as your array is empty.
Very simple question:
You told it stops on an exception. Fair enough. What for an exception? Let me guess, an out of bounds exception? The exception tells you what's wrong in most cases.
replaceObjectAtIndex:0 : is there something at that index or not? Probably not.
In your code you test the condition:
if(!_variableToBePassedIntoTheDictionary)
and if the condition is true, that is the array is nil, then you alloc-init it.
In the following statement:
[_variableToBePassedIntoTheDictionary replaceObjectAtIndex:0 withObject:variable];,
you try to replace the object at index 0 with variable. But in the case above, if you just alloc-init the array, it is empty and than you cannot replace the object at index 0 as not existing, and this raises an exception:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM replaceObjectAtIndex:withObject:]: index 0 beyond bounds for empty array'
So what you have to do is to change the last line as follows:
if([_variableToBePassedIntoTheDictionary count]==0) {
[_variableToBePassedIntoTheDictionary addObject:variable]
} else {
[_variableToBePassedIntoTheDictionary replaceObjectAtIndex:0 withObject:variable]
}
As far as the second question about properties, consider that the role of synthesize is to create for you the setter/getter methods based on the attributes you assigned to the #property. In the new Objective-C you don't need to declare the ivar associated to the property (the ivar is the instance variable that represent the property) and the compiler by default assigns the ivar the name of the property. By using the
#synthesize someProperty = _someProperty
convention you specify that you want the ivar to be called _someProperty. The advantage of this approach with respect to the default one is that you cannot confuse accessing to a property using the setter/getter methods and the ivar directly, that is you cannot make possible mistakes like:
someProperty=value
but instead you must write:
_someProperty=value
or
self.someProperty=value
Anyway have a look at Obj-C documentation for this, it is quite exhaustive.

NSarray count throwing out of bounds

I am trying to check the following and all throw an out of bounds error
if ([objects count] < 1)
if ([objects count] == 0)
if ([objects count] <= 0)
All three thrown an out of bounds? How do I use this in an "if/else" statement? Is it not possible to check if an NSArray contains zero objects.
If you just defined the pointer but did not initialize your objects instance, you will get very strange behavior. As a beginning cocoa developer, I got burned at least twice by something like
NSMutableArray *objects;
...
if ( [objects count] == 0 )
{
.... // do something
}
Are you sure you initialized it, e.g. like so:
NSMutableArray *objects = [NSMutableArray array];
because it really should work in that case!
I don't think that these lines of code can cause such an error.
This code will work correctly for any array.
Out of bounds exception means that you tried to call something like
[myArray objectAtIndex:0];
On an empty array. Or, in other words, you tried to access an object that wasn't a part of the array.
You should not get an out of bounds exception since you are not even trying to access an element in the array -- an out of bounds exception should only be thrown if you call objectAtIndex on your array and specify an illegal index.
In general, to prevent against attempting to access a nil or empty array, I usually do something like this:
if(!objects || !objects.count) ...
This way, if objects doesn't exist then objects.count will not be called.
You can also try this.
if(![objects lastObject])
{
//... Do Something
}

Adding objects from another array

I have the following code:
for (int i = 1; i <= [nmaSpread count];)
{
[nmaUserName addObjectsFromArray:[nmaSpread objectAtIndex:i]];
[nmaSpread removeObjectAtIndex:i];
i += 2;
}
I have declared all variables as global, nmaUserName and nmaSpread are both NSMutableArrays, and have been allocated in viewDidLoad.
I want to store all the odd objects from nmaSpread into nmaUsername and then delete the active object at nmaSpread.
However it keeps crashing with this error:
[NSMutableArray addObjectsFromArray:]: array argument is not an NSArray
2011-12-11 21:08:55.123 appName[15671:f803] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSMutableArray addObjectsFromArray:]: array argument is not an NSArray'
nmaSpread itself is an NSMutableArray, but it looks like the objects it contains aren't. When you do [nmaSpread objectAtIndex:i], that returns an object from nmaSpread. This object isn't an array, so to add it, you'd just use addObject:, not addObjectsFromArray:.
There are a few problems with your code.
First off, you've miss-understood what -addObjectsFromArray: does. The actual method you want is just addObject:.
Second, it is dangerous to modify an array while looping through it. The official line from Apple is "this may work in some situations, but don't do it because it might stop working at any point in the future". You need to wait until after you have finished looping through the array, and then delete them. Your current code is definitely doing it wrong.
You could sit down with pen/paper and work out the math to keep it all intact, but it's easier and safer to just do this:
NSMutableIndexSet *indexesToRemove = [NSMutableIndexSet indexSet];
for (int i = 1; i <= [nmaSpread count];)
{
[nmaUserName addObject:[nmaSpread objectAtIndex:i]];
[indexesToRemove addIndex:i];
i += 2;
}
[mmaSpread removeObjectsAtIndexes:indexesToRemove];
NSMutableArray's addObjectsFromArray expects you to pass another array, but you are passing a single object (the one at index 'i')
You can try switching
[nmaUserName addObjectsFromArray:[nmaSpread objectAtIndex:i]];
to
[nmaUserName addObject:[nmaSpread objectAtIndex:i]];
and that will remove the error you are seeing, but then you are likely to run into another problem because you are removing objects from nmaSpread as you go and as a result the indexes for items later in the array get shifted. You should probably change your logic around to deal with that problem.

Terminating the app due to uncaught exception in Objective-C for iPhone app

i've written a for loop in Objective-C, This is how my code looks like
NSString *string = [NSString stringWithContentsOfFile=#"/Users/Home/myFile.doc"];
NSString *seperator=#"\n";
NSArray *mainarray = [string componentsSeparatedByString:seperator];
// Since i want to parse each element of mainarray
for(NSString *s in mainarray)
{
//again parising the string using a new separator
NSString newseparator = #"=";
NSArray *subarray = [s componentsSeparatedByString : newseparator];
//Copying the elements of array into key and object string variables
NSString *key = [subarray objectAtIndex:0];
NSLog(#"%#",key);
NSString *class_name= [subarray objectAtIndex:1];
NSLog(#"%#",class_name);
// create an instance for the class_name
//dont knw how it ll take the value from file and ???
//Putting the key and objects values into hashtable
NSMutableDictionary = [NSDictionary dictinaryWithObject:class_name forKey:key];
}
Whenever i execute this code this crashes my program saying as, Terminating the app due to uncaught exception NSRangeException
How to know the range of array and how to specify the terminating condition in the for loop???and plz let me knw how to handle this exception???
I'm surprised that code even compiles. If I remember correctly, it can't compile unless you have gone to great lengths to turn off a whole bunch of compiler warnings.
NSString newseparator = #";";
That should give an error write there in that you don't have the *.
NSString *key = [subarray objectAtIndex[0]];
NSString *object = [subarray objectAtIndex[1]];
Neither of these lines of code make any sense.
It would appear that you haven't posted the actual code?
Now, getting back to the exception. A range exception will be tossed if you try to access an item at an index that is outside of the range of indexes available in the array. Thus, if componentsSeparatedByString: returned an array of 0 or 1 elements, then [subarray objectAtIndex: 1]; will cause a range exception to be raised.
What you don't want to do is to try and handle the exception using an #catch block. In Cocoa (and iPhone development), exceptions are treated as non-recoverable errors.
So, instead, use the -count method on NSArray to verify that the array actually contains the # of elements you were expecting. Since you are writing a casual parser, this is probably a good idea as a minimal check of input validity.