I need to call a function in Objective-C every x seconds, but this function needs to receive a 2D int as parameter.
- (void)myTimer:(int[2][3]) field {
//Rest of the code
}
I tried to use the userInfo
option to pass this array, but it looks like it only accepts NSObjects
.
int Field[2][3];
memset(Field, 0x00, 6 * sizeof(int));
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(myTimer:) userInfo:Field repeats:YES];
//Error is: Implicit conversion of a non-Objective-C pointer type 'int (*)[3]' to 'id _Nullable' is disallowed with ARC
Is there a way to pass this 2D int or do I need to go with NSObjects
or maybe a global variable?
Thank you
CodePudding user response:
I don't think it's possible to pass a stack-allocated array to NSTimer
(Objective-C is not very friendly to stack-allocated objects in general. You can pass a pointer to such an array, but NSTimer
can outlive almost all stacks in the application, and you may end up with a dangling pointer then) so you at least need to make this array static or global.
Then you can take a pointer to it, and wrap it with NSValue
like this:
static int data[array_rows][array_columns] = { { 0, 1, 2 }, { 3, 4, 5 } };
NSValue *userInfo = [NSValue valueWithPointer:&data];
Alternatively you can allocate the array in the dynamic memory:
int (*array)[array_columns] = malloc(array_rows * array_columns * sizeof(int));
if (array) {
int val = 0;
for (int i = 0; i < array_rows; i) {
for (int j = 0; j < array_columns; j) {
array[i][j] = val ;
}
}
}
NSValue *userInfo = [NSValue valueWithPointer:array];
As you already noticed, NSTimer
takes Objective-C classes as arguments, so NSValue
can be passed as is:
[NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(timerAction:)
userInfo:userInfo
repeats:YES];
Be advised that on the target side the array pointer looks somewhat different. For the static variable you need to dereference the pointer value:
- (void)timerAction: (NSTimer *)timer {
NSValue *userInfo = timer.userInfo;
int (*array)[array_columns] = *(int (**)[array_columns])userInfo.pointerValue;
...
And for the dynamic memory array it's already dereferenced:
- (void)timerAction: (NSTimer *)timer {
NSValue *userInfo = timer.userInfo;
int (*array)[array_columns] = userInfo.pointerValue;
...