I have the following code. It compiles, but crashes. What am I doing wrong ?
- (void)start: (int*)shouldPause
{
NSNumber * oShouldPause = (NSNumber *)shouldPause;
[self performSelectorInBackground:@selector(runThread:) withObject: oShouldPause];
}
and function runThread is
- (void)runThread: (NSNumber*) shouldPause
In general, I want to set some integer outside of the thread and inside of the thread to change behaviour depending on this integer.
Thanks for help!
NSNumber * oShouldPause = @(*shouldPause);
What you did is a common mistake. NSNumber is an object while int is a primitive type. You cast a pointer to a primitive type to a pointer to an object. Compiler allows that as they both are just pointers. Further the code expects an object, trying to send a message and boom. Something went wrong.
Most likely you don't need int* as a parameter. Just int. And therefore then you need to create the number object as follows, without dereferencing:
NSNumber * oShouldPause = @(shouldPause);
As Andrey Chemukha already cited, you cannot cast an int * to NSNumber *.
Another viable option, if you really have a need to pass the pointer versus the contents of the pointer (which is what Andrey has provided code for) is use NSValue. An example of why you may need this is if you have a deferred call but you want that call to have the most up to date value. Note I'm ignoring synchronization aspects here for simplicity.
And while you're at it you should clean up your usage of data types and use either a bool or BOOL to hold your flag.
- (void)start:(BOOL *)shouldPause {
NSValue *oShouldPause = [NSValue valueWithPointer:shouldPause];
[self performSelectorInBackground:@selector(runThread:) withObject:oShouldPause];
}
- (void)runThread:(NSValue *)value {
BOOL *shouldPause = (BOOL *) [value pointerValue];
if (shouldPause) {
// Pause-a-licous
NSLog(@"shouldPause is %d", *shouldPause);
}
}
NOTE THIS HAS CAVEATS!! Meaning, you need to guarantee the lifetime of the pointer else you will have a dangling pointer. So doing this is not for the meek.
To be clear, based on what you asked, I think Andrey's answer is the right thing to do. I'm just adding this as another option for your toolbox.
Also given how you are doing things, you don't even need to use performSelector:withObject:.
- (void)startAlternate:(BOOL *)shouldPause {
[self runThreadAlternate:shouldPause ? *shouldPause : NO];
}
- (void)runThreadAlternate:(BOOL)shouldPause {
// Pause-o-matic
NSLog(@"shouldPause is %d", shouldPause);
}
I'd probably even then go as far as to change the argument to startAlternate: be a BOOL and not a pointer to BOOL. More often than not, it's best to keep things simple.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With