shannah / Java-Objective-C-Bridge

A thin bridge that allows for two-way communication from Java to Objective-C.
123 stars 25 forks source link

How can we test respondsToSelector: ? #5

Open uchuugaka opened 6 years ago

uchuugaka commented 6 years ago

First, I am happy to know this is still alive, as it is awesome! Low level, but awesome.

My question is, what is the approach to test respondsToSelector: ? I ask because the most common, and tragic mistake I have hit again and again is the stringly selector calling and missing a trailing colon on a selector that takes an argument. In pure Objective-C this generally isn't a problem because Xcode corrects it most of the time (it is rare to have valid selectors with and without the colon because even Apple/NeXT learned that was troublesome) also because the exeption thrown will have the selector in the stack trace. Arguably, even the Objective-C runtime could be more forthright about that, but it is also possible the object or its type are not what one expected.

So, I'd like to add this in for debugging (and potentially raise a Pull Request for making it a debug action to check for respondsToSelector: before each call.)

Any tips?

uchuugaka commented 6 years ago

I think I got it, for anyone else's future reference, or correction if wrong.

I was trying to figure out which name of finishedLaunching BOOL property of an NSRunningApplication instance to use. (of course it responds to both... ugh.) But this syntax for calling respondsToSelector: seems to work. In particular it seems one needs to import Pointer from jna

import com.sun.jna.Pointer;

// code that creates an NSRunningApplication instance named runningApp goes here...

String[] selectors = { "isFinishedLaunching", "finishedLaunching" };

for (String aSelector : selectors) {
  Pointer selPointer = ca.weblite.objc.Runtime.INSTANCE.sel_getUid(aSelector);
  System.out.println(String.format("runningApp respondsToSelector \"%s\" ? %b",
                                   aSelector,
                                   runningApp.send("respondsToSelector:", selPointer)));
}
ind1go commented 6 years ago

Have you had continued success with this method? I've been trying to work out the right selector I need (not an ObjC coder...) and I just get true from everything.

uchuugaka commented 6 years ago

No. I cannot get this to line up with my results in Xcode for the same class and methods. I still do not know how to properly check respondsToSelector: with this bridge.

LOG-TAG commented 5 years ago

@uchuugaka @shannah any blog post or tutorials available for a beginner developer to run this test code? Add ObjCBridge.jar and jna.jar to your classpath means macOS java classpath via terminal or via xcode?

shannah commented 5 years ago

There is no need for XCode. ObjCBridge.jar and jna.jar go in your java classpath (e.g. in terminal, or in your IDE, however you build your java project). libjcocoa.dylib needs to be in your java library path.

LOG-TAG commented 5 years ago

Thanks, I will stop bugging you here, are you available in any of the slackgroup for asking more beginner level questions? (email also works if you don't mind)

mojo2012 commented 5 years ago

@uchuugaka have you tried something like this:

var appClass = Runtime.INSTANCE.objc_getClass("NSRunningApplication");
var isFinishedSelPointer = Runtime.INSTANCE.sel_getUid("isFinishedLaunching");
var isFinishedRetPointer = Runtime.INSTANCE.class_respondsToSelector(appClass, isFinishedSelPointer);

It returns a Pointer native@0x1 (I guess this means true?)