Object Class Array Casting for a Method in Objective C - objective-c

I have an object Student with 4 attributes(age,name,department,surname).
and I create an array of that object like this;
Student students[10] blah blah init blah.
then i want to use an Student array as argument for a method;
-(void) displayStudentInArray : (????) studentarray atIndex: (int) index {.....}
'???' are my problem. what do i write there? i ve no idea.
need help. i m new on objective c.

Rather than using C notation the array should be made like this:
NSArray *studentArray = [[NSArray alloc] initWithObjects: student1, student2, student2, ..., nil];
In which case the parameter type will be NSArray
-(void) displayStudentInArray : (NSArray *)studentarray atIndex: (int) index {.....}

The preferred method for creating arrays is using NSArray (or NSMutableArray if you want to modify the array after it is created):
NSArray *array = [[NSArray alloc]initWithObjects:student1, student2...];
Then your method signature would be:
-(void)displayStudentInArray:(NSArray *)studentarray atIndex:(int)index

These answers are correct, but if you really want to use C notation, you just need to add another asterisk to denote a reference to another pointer:
- (void)displayStudentInArray:(Student**)studentArray atIndex:(int)index {
Student* firstStudent = studentArray[1];
//do what you want with the array
}
This is because C arrays are really just pointers to an address in memory. If you wanted a C array for a primitive, it would look like this:
int* arrayOfInts = malloc(yourSize * sizeof(int));
You have an array of objects, but the idea is just the same. You just add one more asterisk to denote that it's a pointer to a pointer to an object.
Student** students = ...

Just write
Student *tempStudent = (array)[0];

Related

Objective C Array of Array of Strings

I'm trying to make an array of array of strings so that I can eventually pull out something like ArrayOfArrays[0][1] = "hi".
NSString *ArrayOne[] = {#"hello", #"hi"};
NSString *ArrayTwo[] = {#"goodbye", #"bye"};
NSArray *ArrayOfArrays[] = {#[*ArrayOne, *ArrayTwo]};
However when I try to do this, I get an error: Initializer element is not a compile-time constant.
I've read that this is because I'm creating an array with dynamic values, though it should be static. Not sure how to work around this.
Any advice on making an array of array of strings?
Use NSArray, or rather NSMutableArray if you want to modify it after creation:
NSMutableArray *arrayOne = [#[#"hello", #"hi"] mutableCopy];
NSMutableArray *arrayTwo = [#[#"goodbye", #"bye"] mutableCopy];
NSMutableArray *arrayOfArrays = [#[arrayOne, arrayTwo] mutableCopy];
There are other ways to initialise it, but this is the only way that allows you to use Objective-C literal syntax.
You cannot store plain ol' C arrays within an Objective-C collection class as your code attempts to do.
You wrote:
it should be static
if this is what you want then your use of C arrays is quite valid, you just got the syntax wrong. You can use:
NSString *arrayOfArrays[][2] =
{ {#"hello", #"hi"},
{#"goodbye", #"bye"},
};
Important: The 2 is the number of elements in the inner array, you do not change it when adding further pairs.
This will give you a compile-time static array.
If what you are making is a map from one word to another you might be better off with a dictionary, e.g.:
NSDictionary *wordMap =
#{ #"hello" : #"hi",
#"goodbye" : #"bye"
};
and accessing an element becomes:
wordMap[#"hello"];
Note: the dictionary "constant" here is actually executed code; the C array version can appear as a global or local initialiser, while the dictionary initialisation must be done in a method/function - but it can assign to a global.
HTH
NSArray *array = #[
#[[ #"hello", #"hi" ] mutableCopy],
#[[ #"goodbye", #"bye" ] mutableCopy],
];
NSLog(#"%# is short for %#", array[0][1], array[0][0]);
Output: hi is short for hello

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];

variable length c array

I am using objective c to create a struct holding a variable length array. I know you can create an array of length n like so:
double array[n];
And i also believe in c++ you can declare:
vector<double> array;
where you do not have to declare the array length. Is there any way to do something similar in objective c? I am using ARC.
Thanks in advance, Ben
You just need to create an NSMutableArray like-
NSMutableArray *myArray = [NSMutableArray array];
[myArray addObject:....];// Add as many object as you want.
You just need to take care of one thing while creating variable length array, don't add nil as object, as nil is just to signify the end of the variable-length argument list.
EDIT -
Might be following will help you -
In this way you can define objective c data types in struct-
typedef struct{
int numInputs;
__unsafe_unretained NSMutableArray *array;
} Pin;

Why does fast enumeration not skip the NSNumbers when I specify NSStrings?

I thought that I knew how to use fast enumeration, but there is something I don't understand about it. If I create three NSString objects and three NSNumber objects and put them in an NSMutableArray:
NSString *str1 = #"str1";
NSString *str2 = #"str2";
NSString *str3 = #"str3";
NSNumber *nb1 = [NSNumber numberWithInt:1];
NSNumber *nb2 = [NSNumber numberWithInt:2];
NSNumber *nb3 = [NSNumber numberWithInt:3];
NSArray *array = [[NSArray alloc] initWithObjects:str1, str2, str3, nb1, nb2, nb3, nil];
then I make do fast enumeration on all NSString objects, like this:
for (NSString *str in array) {
NSLog(#"str : %#", str);
}
In the console, I get this result :
2011-08-02 13:53:12.873 FastEnumeration[14172:b603] str : str1
2011-08-02 13:53:12.874 FastEnumeration[14172:b603] str : str2
2011-08-02 13:53:12.875 FastEnumeration[14172:b603] str : str3
2011-08-02 13:53:12.875 FastEnumeration[14172:b603] str : 1
2011-08-02 13:53:12.876 FastEnumeration[14172:b603] str : 2
2011-08-02 13:53:12.876 FastEnumeration[14172:b603] str : 3
I logged only the NSStrings, but I get a line for every object in the array, even the NSNumbers and I don't understand why. Does fast enumeration always use every object contained in an array?
When you write a forin loop like that, it casts every object in the array as an NSString, then prints them out as requested.
If you want only the NSStrings, you would need to write something like this:
for (id obj in array) {
if ([obj isKindOfClass:[NSString class]]) {
NSLog(#"str: %#", obj);
}
}
The for all loop doesn't know the difference between NSStrings and Integers -- it will simply go through the entire array, cast each as an NSString, and print them out as you asked.
I'm pretty sure that fast enumeration returns all objects in the array- all that you're doing in for (NSString *str in array) is typecasting str to an NSString. In the body of the loop you need to check the class of the returned object to make sure that it is an NSString.
for(NSString *str in array)
{
if([str isKindOfClass:[NSString class]])
NSLog(#"str : %#", str);
}
Objective-C is dynamically typed, meaning that at runtime (when the loop actually runs), objects are all effectively one type (id) with different classes. The language allows optional compile-time static typing, but all that does is check whether the messages you're sending are valid for the type you've marked. It doesn't actually change the behavior of your program. If you cast an object to be a different type than it actually is, all you're doing is lying to the compiler and defeating its type-checker.
Every object that descends from NSObject implements the method - (NSString)description, %# in Objective-C formate string will take the corresponding argument for the %# and call its description method, Most subclasses of NSObject will implement there own version of - (NSString)description. The same thing happens when you type
> po anObject
in the debugger.
for (NSString *str in array) {
is a way to enumerate through all the elements in array.
You expectative that by specifying NSString you get only the objects of that type is not correct. Rather, all the objects pointers are cast to that type (NSString*).
Have a look at Fast Enumeration in The Objective-C Programming Language guide.
I don't understand where is the unexpected behavior, using the enhanced for loop in an NSMutableArray will just iterate thru every single object in the array which in your case is 6, the result is correct and expected.
The numbers will just get casted to Strings.
in fast enumeration no typecasting,just assigning the pointer into new object

create array of single ivar from array objects with multiple ivars

if i have an class with two properties "a" and "b" and i have an array of these class instances. What is the best way to create an array of only only "a" elements.
The simplest way is Key-Value Coding:
[yourArray valueForKey:#"a"];
Just iterate over the class instances and build your new array:
// Presuming some NSArray * classInstances of type MyClass
NSMutableArray * aProperties = [[[NSMutableArray alloc]
initWithCapacity:[classInstances count]]
autorelease];
for(MyClass * myInstance in classInstances) {
[aProperties addObject:[myInstance a]];
}
If your class is key-value coding compliant for a, you can also ask the array for the values directly:
NSArray * aProperties = [classInstances valueForKey:#"a"];