Why would a function defined in the same class be considered undeclared? How to declare it properly? - objective-c

I'm getting the error "undeclared identifier" on the commented line:
- (BOOL) isInIntArray:(NSInteger[])array theElem:(int)elem{
int i = 0;
NSInteger sizeOfArray = (sizeof array) / (sizeof array[0]);
while(i < sizeOfArray){
if(array[i] == elem){
return TRUE;
}
i++;
}
return FALSE;
}
- (int)getNextUnusedID{
int i = rand()%34;
while ([isInIntArray:idsUsed theElem:i]) { //here: Use of undeclared identifier 'isInIntArray'
i = rand()%34;
}
return i;
}
I really don't understand why, they are in the same .m file.
Why would that be?
Also, this code:
NSInteger sizeOfArray = (sizeof array) / (sizeof array[0]);
is giving me the warning:
Sizeof on array function will return Sizeof 'NSInteger *' (aka: 'int *') instead of 'NSInteger[]'"
How should I properly determine the size of an array?

It looks like you've missed out self from this line
while ([isInIntArray:idsUsed theElem:i])
This should be:
while ([self isInIntArray:idsUsed theElem:i])

As #CaptainRedmuff pointed out, you are missing the target object in method invocation, that is self.
//[object methodParam:x param:y];
[self isInIntArray:idsUsed theElem:i];
To your second Q. In C language you cannot determine the size of an array. That's why they are not used, since we have objects for this. I recommend you to use these:
NSMutableArray *array = [[NSMutableArray alloc] init]; // to create array
array[0] = #42; // to set value at index, `#` creates objects, in this case NSNumber
[array insertObject:#42 atindex:0]; // equivalent to the above
NSInteger integer = array[0].integerValue; // get the value, call integerMethod to get plain int
integer = [[array objectAtIndex:0] integerValue]; // equivalent to the above
[array containsObject:#42]; // test if given object is in the array
[array indexOfObject:#42]; // get index of object from array, NSNotFound if not found
array.count; // to get the number of objects
Important: These arrays have variable size and they are not limited! But you can access elements only at indexes 0..(n-1) (where n in number of objects) and you can set values only for indexes 0..n.
In other words, you can not do array[3] = #42; for empty array, you need to fill first 3 positions first (indexes 0, 1 and 2).

write this in .h file (declare the function)
- (BOOL) isInIntArray:(NSInteger[])array theElem:(int)elem;
and call the method using following way
while ([self isInIntArray:idsUsed theElem:i]) { //here: Use of undeclared identifier 'isInIntArray'
i = rand()%34;
}

Related

Inserting NSNumber into NSMutableArray

allTiles is an NSMutuableArray declared with a capacity of 9. Next a loop inserts 9 NSNull objects with a method called resetArray. I have a method called addToArray which accepts an NSNumber and index at which to insert the value at.
In another class I have int currentTileValue = [self getTileValue]; which returns a tile value. This value will be both the number into the array as well as the index. Whenever I attempt to add to the array it crashes with no indication of why.
allTiles = [[NSMutableArray alloc] initWithCapacity:9];
[self resetArray:allTiles];
- (void) resetArray:(NSMutableArray*) array {
for (int i = 0; i < 9; i++) {
[array insertObject:[NSNull null] atIndex:i];
}
}
- (void) addToArray:(NSNumber*)value :(int)index {
[allTiles insertObject: value atIndex:index];
}
//Different class
//Here is where I am trying to insert into the array.
[(BoxView *)self.superview addToArray:(NSNumber*)currentTileValue :currentTileValue];
What would be causing this to crash?
You state that currentTitleValue is an int. Given this, you need to change this line:
[(BoxView *)self.superview addToArray:(NSNumber*)currentTileValue :currentTileValue];
to:
[(BoxView *)self.superview addToArray:#(currentTileValue) :currentTileValue];
You can't cast an int to an NSNumber pointer. You need to convert it.
Also, your addToArray method is incorrect. Since you pre-populate the array with 9 NSNull objects, you need to call replaceObjectAtIndex:withObject:, not insertObject:atIndex (this assumes you just want 9 values at all times):
[allTiles replaceObjectAtIndex:index withObject:value];
You should also rename your addToArray:: method to something better:
- (void)addToArray:(NSNumber*)value index:(int)index {

How can I pass a C array to a objective-C function?

I'm not familiar with C. How can I pass a C array to a Objective-C function ?
I actually need an example of a class function converting NSArray to C arrays.
This is what I have so far:
+ (NSArray *)convertArray:(NSString*)array { //I don't think this is correct: the argument is just a NSString parameter and not an array
NSMutableArray * targetArray = [NSMutableArray array];
for (i = 0; i < SIZE; i++) //SIZE: I dunno how to get the size of a C array.
{
[targetArray addObject: [NSString stringWithString:array[i]];
}
return targetArray;
}
There are a few ways.
If your array size is fixed at compile-time, you can use the C99 static modifier:
-(void) doSomething:(NSString *[static 10]) arg
{
}
If not, you have to pass it as two separate arguments. One as a pointer to the first element of it, and the second as the length of it:
-(void) doSomething:(NSString **) arg count:(size_t) count
{
}
Now you can access your variables like any other array you may have.
Because you are dealing with a C-array of objective-c objects, you can actually use NSArray's built in constructor for turning a C-array into a NSArray:
NSArray *result = [NSArray arrayWithObjects:arg count:count];

Returning an array (Warning: Function returns address of local variable)?

Returning an array (Warning: Function returns address of local variable) ?
interface
int* decimalConversion(int iX);
implementation
int* decimalConversion(int iX){
int iMult[10] = {0,0,0,0,0,0,0};
...
return iMult; // <-- Warning: Function returns address of local variable
}
You should allocate space for the array, you're returning the address of an array that was created on the stack (hence local variable warning) if you're using C in that function use malloc(my_arr_size) if not use obj-c's alloc.
Example:
int *my_arr = calloc(10, sizeof(int)); //make sure we get zeroed memory
//fill array
return my_arr; //should no longer give a warning
When done with it just use free(my_arr) same as release. Reason I did this in C is because I can see that you're returning an int* type and using C style declarations so if you're doing it in Obj-c let me know and I can change my answer's example.
The reason you are getting this error is because local arrays get put on the stack, when you return that array you return an address in a stack frame. The problem is that when that method finishes execution that stack frame is no longer valid and therefore you cannot expect any data that was on that frame to be valid (although there are cases when this does work but it is considered bad practice). By allocating that array on the heap you can return a heap address where your data is assured to exist until you call free() on the pointer to that data.
If you are doing this for an app written in Objective-C, I would suggest using NSArray. NSArray is an Objective-C class for immutable arrays, and doesn't require that you manually allocate memory. The only turnoff is that you have to encapsulate your integers in NSNumber objects. An example would be:
NSArray * getNums (int num) {
NSArray * result = [NSArray arrayWithObjects:[NSNumber numberWithInt:num-1], [NSNumber numberWithInt:num], [NSNumber numberWithInt:num+1], nil];
return result;
}
...
NSArray * myList = getNums(10);
NSLog(#"First: %d", [[myList objectAtIndex:0] intValue]);
NSLog(#"Second: %d", [[myList objectAtIndex:1] intValue]);
NSLog(#"Third: %d", [[myList objectAtIndex:2] intValue]);
You can alternatively do this:
NSArray * getNums (int num) {
NSMutableArray * array = [NSMutableArray array];
[array addObject:[NSNumber numberWithInt:num-1]];
[array addObject:[NSNumber numberWithInt:num]];
[array addObject:[NSNumber numberWithInt:num+1]];
return array;
}
...
NSArray * myList = getNums(10);
for (int i = 0; i < [myList count]; i++) {
NSLog(#"myList[%d] = %d", i, [myList objectAtIndex:i]);
}
The only difference is that NSMutableArray allows you to add/remove elements after the fact.

Getting the size of an array

i have some code that requires the use of a for loop to read variables from an array.
int size=sizeof names;
NSLog(#"thelast one is %d",size);
NSString *usersName=userName.text;
NSString *usersPass=passWord.text;
for (i=0; i<=size;i++){
NSString *namesArray=[names objectAtIndex:i];
NSString *passArray=[pass objectAtIndex:i];
NSLog(#"namesArray %#",namesArray);
NSLog(#"passArray %#",passArray);
if([namesArray isEqualToString:usersName]){
userValid=1;
NSLog(#"The content of arry4 is %#",namesArray);
}
if([passArray isEqualToString:usersPass]){
passValid=1;
NSLog(#"The content of arry4 is %#",passArray);
}
else {
userValid=0;
passValid=0;
}
}
I've been having some problems because every time this function is called from within the program, it's almost as if the 'sizeof names' is wrong, therefore not all values in the array are checked.
I'm generally a Java programmer so i'm used to names.length, and i was told sizeof names is essentially the same thing... any help?
Cheers.
Don't use sizeof. Use [names count].
You want to use [names count] not sizeof names. Sizeof is going to give you the size of the actual names object pointer itself and not the number of elements, since it's dynamic memory type.
To get the number of elements stored in an NSAarray you should use the instance method count, which returns an NSUInteger.
Alternatevely, you can iterate over these elements using the for in loop, which is available also in Java, if I recall correctly.
for (MyClass *element in myArray) {
NSLog(#"%#", element);
}
Note that sizeof is a C operator that returns the size in bytes of its operand, so it doesn't tell you how many elements are stored in that NSArray, but the size in bytes of one NSArray instance.
I know your question has already been answered - but here is a more Cocoa way of writing it
NSString *userName = userName.text;
NSString *userPass = passWord.text;
// Use a block enumerator
NSUInteger nameIdx = [names indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {
return ([obj isEqualToString:userName]);
}];
// Is the name in the array
if (nameIdx == NSNotFound) {
// Name not in array - so set to zero
userValid = 0;
passValid = 0;
} else {
userValid = 1;
// See if the corresponding password is correct
NSString password = [pass objectAtIndex:nameIdx];
if (![password isEqualToString:userPass]) {
passValid = 0;
} else {
passValid = 1;
}
One can also use Fast Enumeration, in some cases it can be more clear to a reader:
NSString *userName = userName.text;
NSString *userPass = passWord.text;
BOOL userValid = NO;
BOOL passValid = NO;
int index = 0;
for (NSString *eachName in namesArray) {
if ([eachName isEqualToString:userName) {
userValid = YES:
if ([[passArray objextAtIndex:index] isEqualToString:passWord) {
passValid = YES;
}
break;
}
index += 1;
}

Access C Array within blocks (variable array count) Objective-C

Blocks are fine but what about writing C arrays?
Given this simplified situation:
CGPoint points[10];
[myArray forEachElementWithBlock:^(int idx) {
points[idx] = CGPointMake(10, 20); // error here
// Cannot refer to declaration with an array type inside block
}];
after searching a while found this possible solution, to put it in a struct:
__block struct {
CGPoint points[100];
} pointStruct;
[myArray forEachElementWithBlock:^(int idx) {
pointStruct.points[idx] = CGPointMake(10, 20);
}];
this would work but there is a little limitation I have to create the c array dynamically:
int count = [str countOccurencesOfString:#";"];
__block struct {
CGPoint points[count]; // error here
// Fields must have a constant size: 'variable length array in structure' extension will never be supported
} pointStruct;
How can I access my CGPoint array within a block?
OR
Is it even possible at all or do I have to rewrite the block method to get the full functionality?
Another simple answer which works for me is the following:
CGPoint points[10], *pointsPtr;
pointsPtr = points;
[myArray forEachElementWithBlock:^(int idx) {
pointsPtr[idx] = CGPointMake(10, 20);
}];
Maybe you can allocate the array on the heap?
// Allocates a plain C array on the heap. The array will have
// [myArray count] items, each sized to fit a CGPoint.
CGPoint *points = calloc([myArray count], sizeof(CGPoint));
// Make sure the allocation succeded, you might want to insert
// some more graceful error handling here.
NSParameterAssert(points != NULL);
// Loop over myArray, doing whatever you want
[myArray forEachElementWithBlock:^(int idx) {
points[idx] = …;
}];
// Free the memory taken by the C array. Of course you might
// want to do something else with the array, otherwise this
// excercise does not make much sense :)
free(points), points = NULL;