How to return a array list of non-object type in Objective-C - iphone

I have a method which should return a list of non-object types. Specifically a list of CLLocationCoordinate2D. I would like to have it as a list and not as an NSArray I use the outcome to create a MKPolyLine using
+ (MKPolyline *)polylineWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
With the code below I get an "Array initializer must be an initializer" list.
-(CLLocationCoordinate2D[])pathBetween:(CLLocationCoordinate2D)start and:(CLLocationCoordinate2D)end withNumberofPoints:(int)nrOfPoints{
CLLocationCoordinate2D returnPath[nrOfPoints];
for (int i=0; 1<nrOfPoints; i++) {
float fraction=i/(nrOfPoints);
CLLocationCoordinate2D coord=[self coordinateAtFraction:fraction between:start andEnd:end forAccuracy:.02];
returnPath[i]=coord;
}
return returnPath;
}
If I initialize the list using
CLLocationCoordinate2D returnPath[nrOfPoints]={};
I get "Variable sized object may not be initialized".
If I remove the [] from the method I get "returning 'CLClocationCoordinate2D[nrOfPoints]' from a function with incompatible result type 'CLLocationCoordinate2D'"
Any Ideas?

You are trying to create the array on the stack and then return it. That won't work.
There are several things you can do here:
malloc the array of points.
returnPath = malloc(sizeof(CLLocationCoordinate2D) * nrOfPoints;
This would mean the caller would have to free the returned pointer.
return the array in an NSData
NSMutableData* returnData = [[NSMutableData alloc] initWithLength: sizeof(CLLocationCoordinate2D) * nrOfPoints];
returnPath = [returnData mutableBytes];
// the other stuff
return [returnData autorelease];
This means that you don't have to worry about memory management any more than for any other Objective-C object.
Have the caller supply the array e.g.
-(void) getPath: (CLLocationCoordinate2D*) returnPath // caller allocates a big enough buffer
between: (CLLocationCoordinate2D)start
and: (CLLocationCoordinate2D)end
withNumberofPoints:(int)nrOfPoints
{
// code as question but no allocation or return value
}

CLLocationCoordinate2D returnPath[nrOfPoints]; value for noOfPoints should be available at complile time. if u replace line with CLLocationCoordinate2D *returnPath = (CLLocationCoordinate2D *) malloc(nrOfPoints * sizeof (CLLocationCoordinate2D));
array would be available at run time. But I am not sure sizeof method will return the object size.

As pointed out by Kevin in the comment: you have to do something about the fact that your return argument is a local variable. The reference "returnPath" will point into Nirvana outside your function. Here is a video that explains what happens there, enjoy: http://www.youtube.com/watch?v=6pmWojisM_E
For the array of CLLocationCoordinate2D, look at this post here:
NSMutableArray of ClLocationCoordinate2D
Hope this helps.

Related

is there any way to get the return value from a method by using #selector except using double pointer?

I don't want to use double pointer. I am using a function in simpler form as below.
-(NSString *) getName
{
return name;
}
So what is the correct way to take the returned NSString *?
By using #selector(getName) i am not able to get the returned value name.
Thank you in advance
You should use NSInvocation object instance for calling a selector and resolving returned result.
performSelector: does give you the return value directly.
NSString * s = #"NEXT WE HAVE NUMBER FOUR, 'CRUNCHY FROG'.";
NSString * l = [s performSelector:#selector(lowercaseString)];
NSLog(#"%#", l); // prints "next we have number four, 'crunchy frog'."

How to pass an array to a method and then determine the array's size?

I have this method:
+ (NSData *) createWave: (short[])sampleData {
int i = [sampleData count]; // Warning: Invalid receiver type 'short int *'
}
Inside this method, I'm trying to determine how many elements are in the samples array that was passed in. But I'm getting the warning above (I get the same warning if I change samples to short *).
How can I pass an array like this, and then determine the array's size?
You can't.
Either make sure that the last element in your array is unique and check for that or pass in a size parameter as well i.e.
+ (NSData *) createWave:(short [])samples size:(size_t)count {
int i = count;
}
short[] isn't an object so you can't call methods on it - that's why you're getting a warning (and probably a crash if you run the code!)
You are trying to use a C style array as a parameter and then access it as an Objective-C object. (I am assuming sampleData and samples are supposed to be the same). Use an NSArray of NSNumbers instead because with C style arrays you need to know the length.
+ (NSData *) createWave: (NSArray*)sampleData {
int i = [sampleData count];
}

address of ivar as an argument

I am trying to call function but I get error:
warning: passing argument 1 of 'drawPlot' from incompatible pointer type
//call
drawPlot(&listData);
//header
void drawPlot(NSMutableArray*);
listData is of course NSMutableArray
Remove the &. Your variable is already a pointer. I assume you've declared it like so: NSMutableArray *listData;.
So using & is passing a "pointer to a pointer" to a function that is expecting simply a pointer to an NSMutableArray.
Now, there are a number of places in the SDK that expect NSError **. And this is when you would use &, e.g:
NSError *error = nil;
...
[SomeClass doSomethingReturningError:&error];
if (error != nil) {
//something bad happened
}
So, the difference here is that passing, in your case, listData passes the object by value. The variable's value itself cannot be modified (but the contents of the array can be). The other case (&error) is passing by reference, which means that the the value of the variable, i.e. the pointer itself, can be modified. That is why you can compare the result, in that case, to nil to see if something went wrong.
A simpler example is to compare the difference between the following:
void changeIntByValue(int i)
{
i++;
}
void changeIntByReference(int &i)
{
i++;
}
int x=2;
changeIntByValue(x);
NSLog(#"%d", x); // prints 2
changeIntByReference(&x);
NSLog(#"%d", x); // prints 3
Passing by value does not allow arguments to be modified, while passing by reference does.
Definition of listData should look something like:
NSMutableAarray listData; //OR
NSMutableAarray listData[];
If the former, then change the drawPlot call to
drawPlot(&listData[0]) // OR
drawPlot(listData)
If the latter, then change the drawPlot call to
drawPlot(&listData [ the index of the listData array member you want to plot]); // does it work now?

how to pass pointer and got the result in function?

please see code as follow :
- (BOOL)postAction :( NSString*) url params:(NSDictionary*) params bodySize:(NSNumber**)bodySize
{
...
int size = 1999;
NSNumber* value =[[NSNumber alloc] initWithInt:size];
bodySize = &value;
...}
use the function as follows:
NSNumber* size ;
[self postAction:#"http://webserver/ss.php" params:params bodySize:&size];
// can not got the size value at all…
int i = [size intValue];
//will throw nil exception !
my question is that how to correct this code above ?
many thanks for your help !
Regards
If you are using pass-by-reference in iOS or Mac OS X, you are probably doing it wrong.
Seriously-- pass by reference is an exceedingly rare pattern to use. It is pretty much entirely reserved to (NSError**) across the APIs.
Not to say that there isn't a reason to use pass-by-reference, but this isn't it.
Specifically, if you need to return an NSNumber, then return it!
- (NSNumber *) foo;
If that method returns nil, that is just as good as returning a BOOL NO. And it sets you up to follow the very common pattern of using NSError:
- (NSNumber *) foo: (NSError **) error;
Ideally, you should always check the pointer before dereferencing it:
If ( bodySize )
*bodySize = value;
I think you want this:
//bodySize = &value;
*bodySize = value;
I agree with the above two answers. To be more clear, NSNumber is an object (Unlike NSInteger or NSUInteger). So you should directly point your pointer to that object.

Storing and retrieving C struct in NSMutable Array

I have the following C Struct defined :
typedef struct {
float x;
float y;
float z;
} metric;
I want to store accelerometer points in an array and do something with it later.
So I have a mutable array that is initialized like so in my viewDidLoad method :
metricsArray_ = [[[NSMutableArray alloc] init]retain];
in my didAccelerate method I create a struct to store the values and add it to the array :
metric metricData;
metricData.x = acceleration.x;
metricData.y = acceleration.y;
metricData.z = acceleration.z;
NSValue *metricObject = [[NSValue valueWithBytes:&metricData objCType:#encode(struct metric)]retain];
[metricsArray_ addObject:metricObject];
Later when i stop polling for data I try iterate over the array and log the values but the values are all zero :
NSEnumerator * enumerator = [metricsArray_ objectEnumerator];
id element;
while(element = [enumerator nextObject])
{
metric metricData;
[element getValue:&metricData];
NSLog(#"x=%f,y=%f,z=%f",metricData.x, metricData.y,metricData.z);
}
What am I doing wrong here ? And is there a better way to store accelerameter data points? I wanted to store them in a struct rather than an object ( although you end up having to use NSValue anyways )
Thanks
My initial thought is: why do you need a metrics struct if you just use it for x/y/z values. There already is an object for that: UIAcceleration.
I have a game that stores instances of UIAcceleration in an NSMutableArray about 60 times per second as they are received in the accelerometer:didAccelerate: callback. Zero performance issues.
(I am using the NSMutableArray as a 'ring buffer'. When more than N obejcts have been added, items are removed from the beginning. SO that I just capture the last N seconds)
I couldn't even compile your code above. I had to make the following change of removing the struct in the #encode(). This then seemed to compile and work.
NSValue *metricObject = [NSValue valueWithBytes:&metricData objCType:#encode(metric)];
There also appears to be an unnecessary retain.