I want to start a new thread using a C function, not an objective-C method. I tried
[NSThread detachNewThreadSelector: #selector(func) toTarget: nil withObject: id(data)];
where I have
void func(void *data) {
// ...
}
and data is a void *, but I get a runtime crash in objc_msgSend, called from
-[NSThread initWithTarget:selector:object:]
What can I do instead? Is it even possible?
Roll your own:
// In some .h file. #import to make the extension methods 'visible' to your code.
#interface NSThread (FunctionExtension)
+(void)detachNewThreadByCallingFunction:(void (*)(void *))function data:(void *)data;
-(id)initWithFunction:(void (*)(void *))function data:(void *)data;
#end
// In some .m file.
#implementation NSThread (FunctionExtension)
+(void)startBackgroundThreadUsingFunction:(id)object
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
void (*startThreadFunction)(void *) = (void (*)(void *))[[object objectForKey:#"function"] pointerValue];
void *startThreadData = (void *) [[object objectForKey:#"data"] pointerValue];
if(startThreadFunction != NULL) { startThreadFunction(startThreadData); }
[pool release];
pool = NULL;
}
+(void)detachNewThreadByCallingFunction:(void (*)(void *))function data:(void *)data
{
[[[[NSThread alloc] initWithFunction:function data:data] autorelease] start];
}
-(id)initWithFunction:(void (*)(void *))function data:(void *)data
{
return([self initWithTarget:[NSThread class] selector:#selector(startBackgroundThreadUsingFunction:) object:[NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithPointer:function], #"function", [NSValue valueWithPointer:data], #"data", NULL]]);
}
#end
NOTE: I wrote the above code and here by place it in the public domain. (sometimes the lawyers like this kind of stuff) It is also completely untested!
You can always remove the NSAutoreleasePool bits if you can guarantee that the thread entry function also creates one... but it's harmless, has no speed penalty what-so-ever, and makes calling arbitrary C functions that much more simpler. I'd say just keep it there.
And you can use it like so:
void bgThreadFunction(void *data)
{
NSLog(#"bgThreadFunction STARTING!! Data: %p", data);
}
-(void)someMethod
{
// init and then start later...
NSThread *bgThread = [[[NSThread alloc] initWithFunction:bgThreadFunction data:(void *)0xdeadbeef] autorelease];
// ... assume other code/stuff here.
[bgThread start];
// Or, use the all in one convenience method.
[NSThread detachNewThreadByCallingFunction:bgThreadFunction data:(void *)0xcafebabe];
}
When run:
2009-08-30 22:21:12.529 test[64146:1303] bgThreadFunction STARTING!! Data: 0xdeadbeef
2009-08-30 22:21:12.529 test[64146:2903] bgThreadFunction STARTING!! Data: 0xcafebabe
Create an Objective-C class with a method that simply calls that function. Take the selector of that method and pass it to NSThread API.
Well, I'm not sure if it's possible, but keep in mind that every Objective-C method has two implicit/hidden arguments, self and _cmd. An IMP is usually typedef'd like this:
typedef id (*IMP)(id,SEL,...);
If you want to jerry-rig methods and selectors, you need to have a method that looks like that:
void func (id self, SEL _cmd, void *firstParameter);
But even after that, you need to register a selector name with the runtime, then you need to associate that selector with the method, but this is done on a class-by-class basis (i.e. classes can have different implementations of the same selector name), so you at least need to have a dummy class.
It is much, much simpler just to create a dummy class and dummy instance of that class than call the various runtime API just to get NSThread to invoke a single C function.
If you don't need NSThread stuff, you can also start a thread with direct POSIX interface.
I want to start a new thread using a C function, not an objective-C method
Then why don't you just use:
POSIX threads,
GCD?
dispatch_async_f() (man) is suited exactly for this purpose.
Related
I have the following dummy architecture: a singleton class that will receive some data, and, at some point(when returnCallback function is called), will return the data using a callback.
#interface Helper: NSObject
{
void (^_completionHandler)(int someParameter);
}
+(Helper *)getInstance;
- (void) doSomethingWithCompletionHandler:(void(^)(int))handler;
#end
#implementation Helper
+(Helper *)getInstance {
static Helper *instance = nil;
#synchronized(self) {
if (instance == nil)
instance = [[self alloc] init];
}
return instance;
}
- (void) doSomethingWithCompletionHandler:(void(^)(int))handler
{
//do things
_completionHandler = [handler copy];
//do things
}
-(void) returnCallback
{
int result;
//do things with result
_completionHandler(result);
//nothing to follow, it just returned the result.
}
#end
Untill now I was calling the helper a single time and everything worked ok.
E.g.
[[Helper getInstance] doSomethingWithCompletionHandler:^(int result){
NSLog(#"I received %d", result);
}];
But now I need to call the helper 2 times, the second one being inside of the first one.
E.g.
[[Helper getInstance] doSomethingWithCompletionHandler:^(int result){
[[Helper getInstance] doSomethingWithCompletionHandler:^(int result){
NSLog(#" Yay, I'm good %d", result);
}];
NSLog(#"They stopped retaining me:( %d", result);
}];
The problem is(as displayed in the log) that the first function callback is released from memory and I cannot access the result variable. A way to resolve that is to keep 2 variables of the callbacks(one with the current one, one with the old one), but what if I'll need the 3rd one? I tried to build an NSMutableArray with the blocks references. But I had to remove them aswell, and I didn't figure out how.(they get copied inside Helper class, so I don't have a reference to that copied object inside the "Testing" class, do I?)
The above code isn't tested as this is more of an architecture-based question. I will however test it and edit the message asap if there are any errors.
Due to the way you have it designed, you can only have one active operation. If you ever try to execute more operations than one at the time, unexpected stuff happens (as in your example).
There is an established pattern for doing stuff like this - take a look at NSOperation and NSOperationQueue, e.g. here
Is it possible to create an Objective-C class that can have an arbitrary number of dynamic properties at runtime?
I want to be able to call mySpecialClass.anyProperty and intercept this inside my class to be able to provide my own custom implementation that can then return an NSString (for instance) at runtime with raising an exception. Obviously this all has to compile.
Ideal would be if I could refer to my properties using something similar to the new literal syntax, e.g. mySpecialClass["anyProperty"].
I guess in a way I want to create something like a dynamic NSDictionary with no CFDictionary backing store, that executes 2 custom methods on property getting and setting respectively, with the property name passed in to these accessor methods so they can decide what to do.
There are at least two ways to do this.
Subscripting
Use objectForKeyedSubscript: and setObject:forKeyedSubscript:
#property (nonatomic,strong) NSMutableDictionary *properties;
- (id)objectForKeyedSubscript:(id)key {
return [[self properties] valueForKey:[NSString stringWithFormat:#"%#",key]];
}
- (void)setObject:(id)object forKeyedSubscript:(id <NSCopying>)key {
[[self properties] setValue:object forKey:[NSString stringWithFormat:#"%#",key]];
}
Person *p = [Person new];
p[#"name"] = #"Jon";
NSLog(#"%#",p[#"name"]);
resolveInstanceMethod:
This is the objc_sendMsg executed by the runtime for all methods:
If you look at the bottom, you have the opportunity to resolveInstanceMethod:, which lets you redirect the method call to one of your choosing. To answer your question, you need to write a generic getter and setter that looks-up a value on a dictionary ivar:
// generic getter
static id propertyIMP(id self, SEL _cmd) {
return [[self properties] valueForKey:NSStringFromSelector(_cmd)];
}
// generic setter
static void setPropertyIMP(id self, SEL _cmd, id aValue) {
id value = [aValue copy];
NSMutableString *key = [NSStringFromSelector(_cmd) mutableCopy];
// delete "set" and ":" and lowercase first letter
[key deleteCharactersInRange:NSMakeRange(0, 3)];
[key deleteCharactersInRange:NSMakeRange([key length] - 1, 1)];
NSString *firstChar = [key substringToIndex:1];
[key replaceCharactersInRange:NSMakeRange(0, 1) withString:[firstChar lowercaseString]];
[[self properties] setValue:value forKey:key];
}
And then implement resolveInstanceMethod: to add the requested method to the class.
+ (BOOL)resolveInstanceMethod:(SEL)aSEL {
if ([NSStringFromSelector(aSEL) hasPrefix:#"set"]) {
class_addMethod([self class], aSEL, (IMP)setPropertyIMP, "v#:#");
} else {
class_addMethod([self class], aSEL,(IMP)propertyIMP, "##:");
}
return YES;
}
You could also do it returning a NSMethodSignature for the method, which is then wrapped in a NSInvocation and passed to forwardInvocation:, but adding the method is faster.
Here is a gist that runs in CodeRunner. It doesn't handle myClass["anyProperty"] calls.
You're asking different things. If you want to be able to use the bracket syntax mySpecialClass[#"anyProperty"] on instances of your class, it is very easy. Just implement the methods:
- (id)objectForKeyedSubscript:(id)key
{
return ###something based on the key argument###
}
- (void)setObject:(id)object forKeyedSubscript:(id <NSCopying>)key
{
###set something with object based on key####
}
It will be called everytime you use the bracket syntax in your source code.
Otherwise if you want to create properties at runtime, there are different ways to proceed, take a look at NSObject's forwardInvocation: method, or look at the Objective-C Runtime Reference for functions to dynamically alter a class...
Guillaume is right. forwardInvocation: is the way to go. This answer gives some more details: method_missing-like functionality in objective-c (i.e. dynamic delegation at run time)
This has even more details: Equivalent of Ruby method_missing in Objective C / iOS
And these are some other lesser known Obj-C features that might help you: Hidden features of Objective-C
Enjoy!
In C# you can create a delegate method, assign it to a variable or pass it into a method as if it were a variable. For example:
public delegate int Lookup(String s);
//...
public static int Evaluate(String exp, Lookup variableEvaluator)
{
//...
}
I heard that in C you can create a pointer to any method and then pass that pointer to a method.
Can anyone give me a simple example of doing that in Objective-C? Of course, I can create an object with a singe method and pass that object into a method. But I am curious if there is a way of doing that similar to that of C# or C.
Lots of ways.
One: the good. Use blocks (closures, lambda calculus, however you call it):
typedef void (^MyCallback)();
- (void)callTheCallback:(MyCallback)blockToInvoke
{
blockToInvoke();
}
MyCallback cb = ^{
NSLog(#"I was called! :D");
};
[self callTheCallback:cb];
Two: the bad. Grab a pointer to the method function itself and call that. (Warning: if you use this approach, I'll sue you.)
- (void)callTheCallback:(IMP)funcPtrToCall withObject:(id)obj selector:(SEL)sel
{
funcPtrToCall(obj, sel);
}
- (void)someCallbackMethod
{
NSLog(#"I was called! :D");
}
IMP implemt = [[self class] instanceMethodForSelector:#selector(someCallbackMethod)];
[self callTheCallback:implemt withObject:self selector:#selector(someCallbackMethod)];
Three: the ugly. Use a delegate:
- (void)delegateMethodOfSomeObject:(SomeObject *)obj
{
NSLog(#"I was called! :D");
}
SomeObject *obj = [[SomeObject alloc] init];
obj.delegate = self;
[obj makeThisObjectSomehowCallItsDelegateThatIsCurrentlySelf];
Two quick thoughts come to mind.
The short answer is called "blocks", but it's lower level than is probably recommended for what you need.
The "cleaner" solution (read: higher level) is to pass two params: and object (called "target") and a selector (called "action"). This is a very common pattern in Objective-C, so I'll only demonstrate this one. If you are interested in the blocks idea, check out this doc.
Essentially, the object should be passed as an id, and the selector as a SEL, for which we have the handy #selector() construct:
-(void) doThingWithTarget:(id) targetObj action:(SEL) actionSel {
if([targetObj respondsToSelector:actionSel]) {
[targetObj performSelector:actionSel withObject:self];
}
}
// ...
[thatOtherObject doThingWithTarget:self action:#selector(myMethod:)];
// ... where
-(void) myMethod:(id) sender {
// sender is the calling object, or should be by contract.
}
Objective C uses selectors. http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocSelectors.html
Supposed I have two objective-c classes, LBFoo and LBBar.
In LBFoo I have a method that looks like this:
- (void)doSomethingWithFoo:(NSNumber*)anArgument
{
if(anArgument.intValue > 2)
[LBBar doSomethingWithLBBar];
else
[LBBar doSomethingElseWithLBBar];
}
What I would like to do instead is pass an implementation to LBBar that was not declared ahead of time. (As in dynamically override an existing #selector within LBBar)
I know that an IMP type exists, is it possible to pass an IMP to a class in order to change its selector implementation.
you can use the method_setImplementation(Method method, IMP imp) function in objective-c runtime.
if you want to set an instance method, it would work something like this
method_setImplementation(class_getInstanceMethod([yourClass class], #selector(yourMethod)), yourIMP);
if you want a class method, just use class_getClassMethod instead of class_getInstanceMethod. The arguments should be the same.
that's all there is to it. Note that IMP is just a void function pointer with the first 2 parameters being id self and SEL _cmd
You can certainly use the runtime functions to do something like this,* but I'd suggest that this is exactly the sort of problem that Blocks were introduced to solve. They allow you to pass around a chunk of executable code -- your method can actually accept a Block as an argument and run it.
Here's a SSCCE:
#import <Foundation/Foundation.h>
typedef dispatch_block_t GenericBlock;
#interface Albatross : NSObject
- (void)slapFace:(NSNumber *)n usingFish:(GenericBlock)block;
#end
#implementation Albatross
- (void)slapFace:(NSNumber *)n usingFish:(GenericBlock)block
{
if( [n intValue] > 2 ){
NSLog(#"Cabbage crates coming over the briny!");
}
else {
block(); // Execute the block
}
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
Albatross * p = [Albatross new];
[p slapFace:[NSNumber numberWithInt:3] usingFish:^{
NSLog(#"We'd like to see the dog kennels, please.");
}];
[p slapFace:[NSNumber numberWithInt:1] usingFish:^{
NSLog(#"Lemon curry?");
}];
}
return 0;
}
*Note that using method_setImplementation() will change the code that's used every time that method is called in the future from anywhere -- it's a persistent change.
Here's a simple class:
#import "One.h"
#import "Two.h"
#implementation DataFileRegistrar
static NSMutableDictionary *elementToClassMapping;
+ (void)load
{
[self registerClass:[One class] forElement:#"one"];
[self registerClass:[Two class] forElement:#"two"];
}
+ (void)registerClass:(Class)class forElement:(NSString *)element
{
if (!elementToClassMapping) {
elementToClassMapping = [NSMutableDictionary dictionaryWithObject:class forKey:element];
} else {
[elementToClassMapping setValue:class forKey:element];
}
}
+ (id)classForElement:(NSString *)element
{
return [elementToClassMapping valueForKey:element];
}
#end
The problem is this compiler message:
objc[7172]: Object 0x6840720 of class __NSCFDictionary autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
Any ideas what's going on?
Basically, I want to have a simple class with a couple of class methods and one static dictionary. It would be always used without instantiation. I want to use it for a couple of things right after the app starts and then I want to release its memory. I thought ARC can take care of this.
You should not use autoreleased objects on static variables.
Change line...
elementToClassMapping = [NSMutableDictionary dictionaryWithObject:class forKey:element];
to
elementToClassMapping = [[NSMutableDictionary alloc] initWithObjects:[NSArray arrayWithObject:class] forKeys:[NSArray arrayWithObject:element]];
And also do not call your + (void)registerClass:(Class)class forElement:(NSString *)element from a 2nd thread without creating a autorelease pool.
Your class' +load is calling methods which calls autorelease.
Your class is loaded before main.
You can explicitly create an autorelease pool in +load:
+ (void)load
{
#autoreleasepool {
[self registerClass:[One class] forElement:#"one"];
[self registerClass:[Two class] forElement:#"two"];
}
}
However, it's often better to guarantee the order of your program's initialization and load explicitly before creating any threads in main:
int main(int argc, const char * argv[]) {
#autoreleasepool {
[DataFileRegistrar initializeStaticStuff];
...
what are you doing there is putting the dictionary on the stack (which is frankly stupid, because you have so many ways not to do that) and it leaks because it never gets deallocated from the stack.
NSDictionary is created to be used with autorelease pool (and yes..i know there are some cases where is better to use a static one but those cases are very very rare )
declare NSMutableDictionary *elementToClassMapping; in interface and everything will work just fine