I am tring to create a private 2D float array and initialize it in constructor. I am getting "Expected Expression" error. I searched for a long while and couldn't find anything.
Here is my code:
#interface SampleClass : NSObject{
#private
float stops[2][2];
}
#end
#implementation SampleClass
- (id) init{
self = [super init]; // Edited
stops = { {1.0, 1.0}, {1.0, 2.0} }; // It gives "Expected Expression" at this line
return self;
}
#end
I tried different versions like:
stops = { {1.0, 1.0}, {1.0, 2.0} };
stops = { 1.0, 1.0, 1.0, 2.0 };
stops[][] = { {1.0, 1.0}, {1.0, 2.0} };
Non of them seems to work.
I am new to Objective C so any recommendation is appreciated.
(Objective-)C does not support assignment of one array to another, there are workarounds involving struct as they are assignable but you don't need to go there.
If you are after a constant array to be used by instances you can just declare it as static:
static const float stops[2][2] = { {27.3, 51.7}, {93.2, 42.24}};
The static makes stops accessible only to code within the same file. You can place the declaration between the #implementation and #end to at least visually associate it as belonging to a class.
The above is not suitable if you need a variable array, but does form part of a solution. Keep your instance variable:
#private
float stops[2][2];
This must be an array, not some pointer, as it must allocate the space for your floats. Next use the above declaration but give it a different name:
static const float _stops_init[2][2] = { {27.3, 51.7}, {93.2, 42.24}};
and then in your init use the standard C function memcpy() to copy the values in the memory occupied by _stops_init into the memory occupied by stops:
memcpy(stops, _stops_init, sizeof(_stops_init));
Here sizeof() will return the total size in bytes of the memory used by your float array _stops_init and memcpy() copies those bytes over those associated with stops – that is it implements array assignment which C doesn't directly support.
Using the static const array rather than a local variable define in init() as the source of your values saves re-creating the source on every call to init().
The above code doesn't do all the checks it should - at minimum an assert() checking that the sizes of stops and _stops_init are the same is advisable.
HTH
Related
A double created in Swift
let d: Double = 1.0
when passed to Objective C, will not preserve the .0. It ends up as 1.
Is there a way preserve .0 for whole doubles in Objective C?
Edit:
Here's what I'm doing:
Parent.m
#implementation Parent
-(void)log:(NSDictionary*)data {
}
#end
Parent.h
#interface Parent : NSObject
-(void)log:(NSDictionary*)data;
#end
Child.swift
class Child: Parent {
func log() {
let measure = Double(1)
let isLoggedIn = false
let data: [String: Any] = ["is_logged_in": isLoggedIn, "measure": measure]
log(data) // calling parent method, measure ends up as 1
}
}
From the wording of your question you might need to research the difference between a double value (the same in both languages) and a textual representation of a double value (which your question suggests might not default to the same in both languages).
Once you are clear on that look up the NSString method stringWithFormat and see if you can produce the format you require using that. (NSLog() supports the same formatting.)
If the above fails to meet your requirements look up NSNumberFormatter.
HTH
I currently have this code:
#interface Matrix4 : NSObject
{
float mat[16];
}
#property (readonly) float mat[1];
I want the property to either give me the mat array or have multiple properties giving me readonly access to mat[1], mat[2], etc.
I current have "Property cannot have array of function type float[1]" as an error message
Arrays cannot be return values, so the property cannot have an array type. Instead you must return a pointer, so declare the property as a pointer to the element type of the array:
#property (readonly) float *mat;
Keep the instance variable as float mat[16] as you have now. Then implement the accessor to return a pointer to the array:
- (float *)mat {
return mat; // array decays to pointer automatically
}
Alternatively, you could have an accessor directly for the individual elements:
- (float)matIndex:(NSUInteger)i {
// maybe check bounds here?
return mat[i];
}
The problem with these approaches is that the information about the size of the array is lost, so you would probably want to put the size of the array in a macro or const variable. If you need something a bit more object-oriented, make the array an NSArray and store NSNumbers in it.
edit: One option would also be to wrap the array in a struct to preserve the size info, though you still probably want to pass it around by reference:
struct matrixf16 {
float f[16];
};
#interface Matrix4 : NSObject {
struct matrixf16 mat;
}
#property (readonly) struct matrixf16 *mat;
(Also, if I'm guessing correctly that the size is 16 because it's meant to hold a 4×4 matrix, why not make the array float f[4][4].)
As the compiler is telling you, properties cannot have array or function type.
You can manually implement the getter, like
#interface Matrix4 : NSObject {
float mat[16];
}
- (float *)mat;
#implementation
- (float *)mat {
return mat;
}
or you can consider using an NSArray instead, depending on your requirements. NSArray is definitely more overweight than a native C array, but it allows you to use properties.
However I suspect you have a design issue: it looks like you are trying to implement a squared matrix, but you are exposing the internal representation, most likely so that the client can set the matrix elements.
You should instead hide the internal representation and only expose methods to perform matrix operations. For instance, you can think of exposing a method which sets the matrix value, as:
- (void)setValue:(float)value forRow:(int)row column:(int)col {
NSParameterAssert(row >= 0 && row < 4 && col >= 0 && col < 4)
mat[row * 4 + col] = value;
}
and one that gives you an element back
- (float)valueForRow:(int)row column:(int)col {
NSParameterAssert(row >= 0 && row < 4 && col >= 0 && col < 4)
return mat[row * 4 + col];
}
and make the mat ivar private. This gives you also the flexibility of changing the internal representation at will, without breaking the client's code.
The above implementation is also very easy to generalize to a squared matrix of size, by providing a dimension parameter and using a NSArray or dynamic memory allocation (since variable-length arrays cannot be ivars).
I wanted to create 2 global arrays which can be updated during the run of the programme.In each update i add one element to zeroth position and deleted the last number
I created the arrays as....
In the .h file..........
//////////////
#interface Shared : NSObject{
NSMutableArray *x;
NSMutableArray *y;
}
#property (nonatomic,retain) NSMutableArray *x;
#property (nonatomic,retain) NSMutableArray *y;
+(Shared*)sharedInstance;
#end
In .m file
staticShared* sharedInstance;
#implementation Shared
#synthesize x;
#synthesize y;
+(Shared*)sharedInstance
{
if (!sharedInstance) {
sharedInstance=[[Sharedalloc]init];
}
returnsharedInstance;
}
-(Shared*)init
{
self = [superinit];
if(self)
{
x=[[NSMutableArrayalloc] init];
x=[NSMutableArrayarrayWithObjects:#"0",#"0",#"0",#"0",#"0",#"0",#"0",nil];
y=[[NSMutableArrayalloc] init];
y=[NSMutableArrayarrayWithObjects:#"0",#"0",#"0",#"0",#"0",#"0",nil];
}
returnself;
}
#end
Then i used to call them and re,ove and added elements using the following code....
[[shared sharedInstance].y removeLastObject];
[[shared sharedInstance].y insertObject:new_element atIndex:0];
[[shared sharedInstance].x removeLastObject];
[[shared sharedInstance].x insertObject:new_element atIndex:0];
In the mean time i call these values and calculate an arithmetic value using an expression.
This seems to work well. But it seems to be an inefficient way to handle floating point numbers which i store in it. As these arrays creates objects. Is there any easy method that i can create a global array containing specified amount of floating point numbers and update it during the run of the programm(array size is fixed) by deleting the last object, and call them back to do calculation?
Please help me!
EDIT 1
To sir deanWombourne
.................................
I implement as you instructed! Can you please go through this and help me to correct 2 errors i get.
IN the .h file
#interface Shared : NSObject{
#private
float input[7];
float output[6];
}
+(Shared*)sharedInstance;
-(void)addNewInput:(float)input1;
-(float *)input;
-(void)addNewOutput:(float)output1;
-(float *)output;
#end
in .m file............
#implementation Shared
-(id)init{
if((self =[superinit])){
for(int n=0; n<7 ;++n)
input[n]=0.00f;
for(int n=0; n<6 ;++n)
output[n]=0.00f;
}
returnself;
}
-(void)addNewInput:(float)input1{
input[0]=input[1];
input[1]=input[2];
input[2]=input[3];
input[3]=input[4];
input[4]=input[5];
input[5]=input[6];
input[6]=input1;
}
-(float *)input {
returninput;
}
-(void)addNewOutput:(float)output1{
output[0]=output[1];
output[1]=output[2];
output[2]=output[3];
output[3]=output[4];
output[4]=output[5];
input[5]=output1;
}
-(float *)output {
returnoutput;
}
#end
When calling it
float reading= (accel_reading)/(1.165969038*1e5f);
[[SharedsharedInstance] addNewInput:reading];
Problems i get
1. In the implementation, it says incomplete implementation (it's a warning not an error)
2. How can i used a for loop to fill array values or is this way ok?
Major problem i get,
When i call it as shown above, program stops running telling
Terminating application due to uncaught exception 'NSInvalidArgumentException', reason '+[SharedsharedInstance]: unrecognized selector sent to class 0x5780'
Please help me through this...............
Your code Smells (and I mean that in the nicest possible way!)
Using two parallel arrays and keeping in sync is a bad design pattern (and a performance hit in quite a few ways!). Especially as there is already a struct that handles storing an x and y at the same time - CGPoint).
You're solving the 'only objects go in arrays' problem by converting your float' primitives toNSString` objects, which is horrendously inefficient - take a look instead at the NSValue class, it's designed to put native C primitives into an object without expensive parsing operations :)
You might also want to look into malloc (and free etc) and deal with the whole problem at the C level - this will mean no objects at all and would be blindingly fast (at the cost of more complicated code).
Hope this helps, if you have any questions just add a comment to this answer :)
EDIT
If all you want to do is store 4 x and y values, then this is probably the easiest way to do it :
#interface Shared : NSObject {
#private
CGPoint points[4];
}
+(Shared *)sharedInstance;
- (void)addNewPoint:(CGPoint)point;
- (CGPoint *)points;
#end
#implementation
- (id)init {
if ((self = [super init])) {
// Start with 0,0 for all your points
for (int n = 0; n < 4; ++n)
points[n] = CGPointZero;
}
return self;
}
- (void)addNewPoint:(CGPoint)point {
// Just move all the points along one and add the new one to the end
// (yes, this could be done in a loop but there's not that much point for 4 points!)
points[0] = points[1];
points[1] = points[2];
points[2] = points[3];
points[3] = point;
}
- (CGPoint *)points {
return points;
}
#end
This gives you a method addNewPoint that removes the first point and adds the new point to the end of your array.
You also get the method points that returns the 4 points. Use it something like :
// To add a point
CGPoint newPoint = CGPointMake(100, 100);
[[Shared sharedInstance] addNewPoint:newPoint];
// To do something with the points (in this case, NSLog them)
CGPoint *points = [[Shared sharedInstance] points];
for (int n = 0; n < 4; ++n)
NSLog(#" Point %i : %#", n, NSStringFromCGPoint(points[n]));
EDIT #2
From your comments, you need two arrays, one with input data and one with output data. Try something like this :
#interface Shared : NSObject {
float inputs[4];
float outputs[5];
}
...
This will give you two arrays to read/write to - one called inputs and the other called outputs. Access them in pretty much the same way you did the ones in my first edit :
float *inputs = [[Shared sharedInstance] inputs];
for (int n = 0; n < 4; ++n)
NSLog(#" Input %i : %f", n, inputs[n]);
float *outputs = [[Shared sharedInstance] outputs];
for (int n = 0; n < 5; ++n)
NSLog(#" Output %i : %f", n, output[n]);
Would a linked list be overkill for what you're trying to achieve? It's not quite as simple as a static array of floats, but makes the removal of the last object and insertion of the zeroth object reasonably simple and fast.
If you want an array containing a specific number of Objects, you can use NSArray, which is static, opposed to NSMutableArray.
As for the array being Global, just implement a singleton class that contains the 2 arrays and provides the associated methods.
in Globals.h:
#interface Globals : NSObject
+ (Globals *) sharedGlobals;
#end
in Globals.m:
#implementation Globals
static Globals *sharedGlobals = nil;
+ (Globals *) sharedGlobals{
#synchronized(self){
if (sharedGlobals == nil){
sharedGlobals = [[self alloc] init];
}
}
return sharedGlobals;
}
you then can access the arrays (after you implemented them) with the following line:
[[Globals sharedGlobals] getArrayX];
Here is a sketch to get you going.
Your array size is fixed and only contains floating point numbers, start with a C array:
double x[] = {0, 0, 0, 0, 0, 0, 0};
double y[] = {0, 0, 0, 0, 0, 0};
The number of elements in these arrays can be calculated rather than hard-coded:
int xCount = sizeof(x)/sizeof(double);
int yCount = sizeof(y)/sizeof(double);
Now use these arrays as a circular buffer, declare a cursor and initialise:
int xCursor = 0;
The item at the front of the queue is at the cursor:
valueAtFrontOfQueue = x[xCursor]; // get the current front item
To remove the value at front and add a new one to the rear replace the value at the cursor with the new value and increment the cursor:
x[xCursor] = newValueForBackOfQueue; // replace it with new item for back of queue
xCursor = (xCursor + 1) % xCount; // and advance cursor using mod arithmetic to it cycles around
No wrapping doubles as objects, no dynamic allocation at all.
Wrap the above up as you see fit, maybe as a class, and you're done.
I have got a Matrix-Class from which a Vector-Class is derived from and for extra functionality and better usage I've got a Vector3-Class which is derived from the Vector class. My problem is now that the Vector-class implements a function for instance +normalizeVector: which returns a new allocated Vector-instance. The subclass Vector3 should inherit these two functions but an inheritance leads to the function-prototypes that return a Vector-instance and not a Vector3-instance. This is just how inheritance works but is there a good practice how to solve that problem? A naive solution is to create Vector3 als a new class which subclasses NSObject but I want that Vector- and Vector3-instances can interact easily.
Here an code-example:
#interface Vector : NSObject {
....
}
+(Vector*) normalizeVector:(Vector*)v; //returns a new allocated Vector-instance
-(Vector*) normalize; //normalizes itself and returns itself
-(Vector*) otherFunction;
#end
#interface Vector3 : Vector {
}
-(Vector3*) specialFunction;
#end
usage of that code:
Vector3 *v3 = ...;
[[v3 normalize] specialFunction]; //Compiler gives me a warning because Vector has no specialFunction. Cast would help
[[Vector3 normalizeVector:v3] specialFunction]; //Compiler gives me a warning and during runtime it will crash because a `Vector` doesn't implement specialFunction
a cast to Vector3 would help but is not nice to work with and that also fails with the static function +normalizeVector: because in that static function a Vector-instance is allocated and a pointer-cast doesn't help.
any ideas? or other approaches / other modeling ?
edit: Code for my static function normalizeVector which gets inherited by Vector3:
#implementation Vector
...
+(Vector*) normalizeVector:(Vector *)v
{
unsigned int dim = vector_max(v.cols, v.rows);
Vector *res = [[[Vector alloc]initAsColumnVectorWithDim:dim] autorelease];
[Vector normalizeVector:v destination:res]; // this does only the logic: calc length and divide each component by the len and store at the vector passed to destination
return res;
}
#end
You will notice that -init methods always return type id -(id)init {..} exactly becauase of this.
Also, instead of [Vector alloc] - as you have noticed you don't actually know what Class you are in at runtime (it could be a subclass), so instead just use [self alloc] where self is the current Class because you are in a Class method. So, if you do [Vector3 normalizeVector:v] self is Vector3 and if you do [Vector normalizeVector:v] self is Vector.
Try adjusting your +normailzeVector: method to
+ (id)normalizeVector:(Vector *)v {
unsigned int dim = vector_max(v.cols, v.rows);
id res = [[[self alloc] initAsColumnVectorWithDim:dim] autorelease];
[self normalizeVector:v destination:res];
return res;
}
Just a note, + (id)normalizeVector: is not a function and definitely not a static function. It is a class method, it just helps to get the terms right.
In this case I would make normaliseVector an instance method. So instead of
Vector *newV = [Vector normalizeVector:v];
call
Vector *newV = [v normalizeVector];
Then you can produce a different normalizeVector for Vector and Vector3
EDIT:
For [[v3 normalize] specialFunction]; there is a problem in that normalize can sometimes return an object that specialFunction does not work on - ie it only works if v3 is a Vector3. So in this case there is extra information you have so a cast would be needed or that Vector3 normailze differs from Vector's. In this case I would produce a cover method on Vector3 to call normalize] specialFunction] so that the cast is in Vector3 specific code.
I've got object_getInstanceVariable to work as here however it seems to only work for floats, bools and ints not doubles. I do suspect I'm doing something wrong but I've been going in circles with this.
float myFloatValue;
float someFloat = 2.123f;
object_getInstanceVariable(self, "someFloat", (void*)&myFloatValue);
works, and myFloatValue = 2.123
but when I try
double myDoubleValue;
double someDouble = 2.123f;
object_getInstanceVariable(self, "someDouble", (void*)&myDoubleValue);
I get myDoubleValue = 0. If I try to set myDoubleValue before the function eg. double myDoubleValue = 1.2f, the value is unchanged when I read it after the object_getInstanceVariable call. Setting myIntValue to some other value before the getinstancevar function above returns 2 as it should, ie. it has been changed.
then I tried
Ivar tmpIvar = object_getInstanceVariable(self, "someDouble", (void*)&myDoubleValue);
If I do ivar_getName(tmpIvar) I get "someDouble", but myDoubuleValue = 0 still! Then I try ivar_getTypeEncoding(tmpIvar) and I get "d" as it should be.
So to summarize, if typeEncoding = float, it works, if it is a double, the result is not set but it correctly reads the variable and the return value (Ivar) is also correct.
I must be doing something basic wrong that I cant see so I'd appreciate if someone could point it out.
object_getInstanceVariable is a confused little function. It is documented that the last parameter is a void ** parameter—that is, you pass the address of a void * variable and get a pointer to the instance variable—but it is implemented as if it was a void * parameter—that is, you pass the address of the variable that you want to hold a copy of the instance variable. The problem is that the implementation ignores the size of the instance variable and just does a pointer copy. So anything that's the same size as a pointer will work perfectly. If you're running on a 32-bit architecture, only the high 32 bits will be copied. (You should witness the same behavior with a long long instance variable as well.)
The solution is to use the primary API, key-value coding, using -valueForKey:.
The other solution: If you wanted to write a fixed version, say as a category for NSObject, it would look something like this:
#implementation NSObject (InstanceVariableForKey)
- (void *)instanceVariableForKey:(NSString *)aKey {
if (aKey) {
Ivar ivar = object_getInstanceVariable(self, [aKey UTF8String], NULL);
if (ivar) {
return (void *)((char *)self + ivar_getOffset(ivar));
}
}
return NULL;
}
#end
Then your code would look like this:
double myDoubleValue = *(double *)[self instanceVariableForKey:#"someDouble"];
What about using valueForKey:?
NSNumber * value = [self valueForKey:[NSString stringWithUTF8String:ivar_getName(tmpIvar)]];
NSLog(#"Double value: %f", [value doubleValue];
Note: this requires you to have a "someFloat" method. If you want to use setValue:forKey:, you'll also need the "setSomeFloat:" method. This is easily implemented by declaring the ivar as an #property and synthesizing it.