This question already has answers here:
Using NSString to call a function in XCode 4.x
(5 answers)
Closed 8 years ago.
this is stupid question for execute some function in objC, for example like this:
NSString *function = #"-(void)execute{NSLog(#"123");}"
how to execute that string become a function?
This is not possible, since Objective-C is compiled, not interpreted.
What you can do is add a -(void)execute {...} method in your code. Then if for some reason you need to call this method using a string, you can use [self performSelector:NSSelectorFromString(#"execute")].
But the string can not include any code. It must be limited to being an existing method's name.
I think you are looking for,
1. No Parameter
SEL aSelector = NSSelectorFromString(#"execute");
[self performSelector:aSelector];
Simulation:
-(void)execute;
2. Single Parameter
SEL singleParamSelector = NSSelectorFromString(#"methodWithOneParam:");
[self performSelector:singleParamSelector
withObject:first];
Simulation:
-(void)methodWithOneParam:(NSString*)first;
3. Multi Parameter
SEL doubleParamSelector = NSSelectorFromString(#"methodWithFirst:andSecond:");
[self performSelector: doubleParamSelector
withObject: first
withObject: second];
Simulation:
-(void)methodWithFirst:(NSString*)first andSecond:(NSString*)second;
Can you please describe in detail, what you really want to do. What you describe pretty much looks like runtime code injection, if so just check the following docs about class_addMethod:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/c/func/class_addMethod
and check this good description:
http://distriqt.com/post/846
Not possible. As the others have pointed out, you can create a selector from a string using NSSelectorFromString, and then you can use performSelector:withObject: or it's variants to invoke that method.
Related
Hello I am having trouble using SimplePing I receive the following error when copying over the SimplePing.h and SimplePing.m files I downloaded from Apple SimplePing
No known class method for selector 'simplePingWithHostName:'
From this method in my SimplePingClient.m class:
-(void)pingHostname:(NSString*)hostName andResultCallBlock:(void(^)(NSString* latency))result
{
_resultCallback = result;
_pingClient = [SimplePing simplePingWithHostName:hostName]; // No known class method for selector 'simplePingWithHostName:'
_pingClient.delegate = self;
[_pingClient start];
}
I'm calling this method from another file like this, where there are no errors:
-(void)testNetworkLatency {
[SimplePingClient pingHostname:#"www.apple.com"
andResultCallback:^(NSString *latency) {
NSLog(#"your latency is: %#", latency ? latency : #"unknown");
}];
}
I tried changing [SimplePing simplePingWithHostName... in SimplePingClient.m to variations of pingHostname, initWithHostName, sendPingWithData but nothing has worked so far. Did something change with SimplePing or am I going wrong somewhere?
Link to a screenshot of all the methods available in SimplePing.h as you can see, there is no simplePingWithHostName
it is wise to read the class definitions before coping and pasting but once done you can take them for granted because thats what they are for. You will have much more fun when following them. But keep on trying as this is a classic beginner mistake in objC when taking over language concepts from elsewhere but not objC.
You will want to set a global variable to keep your simple ping object around.
#implementation YourClass {
SimplePing *_pingClient;
}
alternative in
#interface YourClass : YourInheritingClass <NeverGiveUpProtocol>
#property (nonatomic) SimplePing *pingClient;
#end
and in your implementation method allocation and initiation of your ping object is done like
_pingClient = [[SimplePing alloc] initWithHostName:hostName];
Also you will have to be careful with the definition of block parameters that are doing nothing and are set up to accept NSStrings. You can read about block definitions in methods here
https://riptutorial.com/objective-c/example/1761/blocks-as-method-parameters
You can tell the compiler that you don't need a specific parameter like so ..
if you cant avoid to define it.
-(void)yourmethod:(NSString*)hostname resultBlock:(void(^)())result {
#pragma unused(result)
// your stuff
}
Hint: SimplePing and SimplePingClient seem to be total different classes where the last one contains pingHostname: as external method. (Means you can call it without explicit initiation.) Ending up in a method definition like..
+(void)pingHostname:(NSString *)hostname; which is why you would need to call it directly on the ClassName.
The Apple example does not contain a class named SimplePingClient.
Thats probably result of your creative process. Yeah maybe you want to ping from the app you create to the same app on a different device - well, why not. Cheers
I have the following method section
- (NSString*) GetPathForFolder:(int)folder inDomains:(int) domains {
id cls = objc_getClass("NSFileManager");
SEL defaultManagerSelector = #selector(defaultManager);
SEL urlsForDirectoryInDomainsSelector = #selector(URLsForDirectory:inDomains:);
id fileMangerHandle = objc_msgSend(cls, defaultManagerSelector);
//NSArray<NSURL *>* notUsedArray = [fileMangerHandle URLsForDirectory:folder inDomains:domains];
NSArray<NSURL *>* resultArray = (NSArray<NSURL *>*) objc_msgSend(fileMangerHandle, urlsForDirectoryInDomainsSelector, folder, domains);
return [resultArray lastObject].absoluteString;
}
Calling this method with [self GetPathForFolder:5 inDomains:1]
returns file:///Applications/ which is wrong
The moment I uncomment the NSArray<NSURL *>* notUsedArray.. line I get a different and correct value which just happens to be the same as the one from
What does the objective-c version of the call do that I'm not doing in my C version?
Update:
I'm using objc_msgSend because this method will eventually be called from C# but it's just easier to first try it in objective-c and than start worrying about the interop part.
I was using sel_registerName because when running this inside of C#, I'm going to have to do my own registration.
More about Interop between C# and objective-c here. And also a java version of what I'm trying to understand is here.
You can’t use objc_msgSend like this, it is not a variadic function, even though it’s prototype suggests it. The compiler needs to use the same calling convention that the method is expecting. For this it needs to know the exact types of all parameters. You can tell it by casting objc_msgSend to a function pointer type with the correct parameters.
So for this case you would use something like this:
typedef NSArray<NSURL *> *(*UrlsForDirectoryType)(id, SEL, NSUInteger, NSUIteger);
NSArray<NSURL *>* resultArray = ((UrlsForDirectoryType)objc_msgSend)(fileMangerHandle, urlsForDirectoryInDomainsSelector, folder, domains);
The typedef is optional, of course, but then that makes the whole thing even harder to read.
To expose this to a different programming language you could also write regular C functions in Objective-C and call those. This is much easier to do than dealing with the runtime directly.
This question already has answers here:
Objective-C find caller of method
(12 answers)
Closed 7 years ago.
Is it possible to know which function calls the current function in the objective-c?
for example, I have 100 functions give a call to function X. In the function X, are we able to define which function from 100 functions has already called?
Thanks.
I'm using a define directive :
#define CALLER_OF_METHOD NSLog(#"My Caller: [%#]", [[[[NSThread callStackSymbols] objectAtIndex:1] componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"[]"]] objectAtIndex:1])
please try, let me know if it's works for you chipbk10
if you dont want to write any code, put a break point in the function, then on the left it will show you the calling tree and you can see what functions were called in order to get to that breakpoint
Need to run application set break point in function X. When application stops at break points check functions in Debug navigator in xcode. you will know that which function called function X.See the sequence in below image.
I'm trying to use CoreBluetooth's retrievePeripheral :
- (void)retrievePeripherals:(NSArray *)peripheralUUIDs;
The documentation says peripheralUUIDs should be a NSArray of CFUUIDRef. In the Apple sample project temperatureSensor, it is called as :
[centralManager retrievePeripherals:[NSArray arrayWithObject:(id)uuid]];
(uuid being a CFUUIDRef)
When I use the exact same code in XCode 4.5.1, IOS6, I'm getting a error :
Cast of C pointer type 'CFUUIDRef' (aka 'const struct __CFUUID *') to Objective-C pointer type 'id' requires a bridged cast
I would say (though I'm far from sure) that the reason it works in TemperatureSensor and not in my project is because TemperatureSensor seems not to use ARC whereas my project does.
Xcode suggests 2 ways of solving the problem : adding a __bridge or using CFBridgingRelease(). I tried them both and I'm under the impression that the function does not work [Edit] because the delegate methode didRetrievePeripheral: never gets called [/Edit] (my understanding is that these operation would change the C-style structs into objective-C-objects thus creating a NSUUID, and the method can't use it, but, again I'm really not sure)
So what should I do ? I've been searching on google for examples of retrievePeripherals using ARC, but without success.
In the temperature sensor change this line and run
LeDiscovery.m
-(void) startScanningForUUIDString:(NSString *)uuidString
{
[centralManager scanForPeripheralsWithServices:nil options:0];
}
change the word nil and assume 0.
If you want more check this link.
I hope its useful for you.
Turns out the problem was much simpler than that. I copied/pasted some code from TemperatureSensor, specifically the DidRetrievePeripheral. But it turns out, there's an error in this code (it's DidRetrievePeripheralS), so the delegate method never gets called. I think the bug is already reported.
Thanks/sorry
I am trying to declare a function in my .h file that looks like this:
-(*NSString) encode: (NSString*) unencodedString;
and I get a syntax error:
expected a type
Here is my .m header for this function:
- (NSString*)encode: (NSString*) unencodedString
and here is how I am trying to call it:
EncodingUtil *encode_object = [[EncodingUtil alloc] init];
NSString *encoded_company_name = [encode_object encode: name];
Could someone please help me understand what I am doing wrong and how to fix it?
Thanks!
Your return type says (*NSString). That's completely backwards. You want (NSString*).
Of course it does (and you should really learn C first, you'll get lost in Obj-C if you don't even know how to declare a pointer type!). What you presumably wanted to write is
- (NSString *)encode:(NSString *)unencodedString;