Although the docs do provide some helpful information when using Declare, I still struggle a bit to understand a few things (specifically with regards to macOS).
As a result, a lot of the time I just copy and paste from either Sam’s AppKit or the macOSLib repo, when I need something not in the Xojo toolkit.
Question: Using Selector respondsToSelector: as an example, it appears this can be called with either Lib “Cocoa” or “Foundation”.
Is this because the “Cocoa” framework encompasses all (or most) libraries in the macOS API? As the Apple literature suggests.
If yes to the above, does that mean calling “Cocoa” routes the Selector request to “Foundation”?
Or does respondsToSelector: exist in both places and is potentially executing slightly different logic?
And if respondsToSelector: exists only in “Framework”, is there a performance difference calling “Cocoa” verses “Foundation” directly? Or something else important I’m missing?
// what's the difference besides what Lib is being called?
Declare Function respondsToSelector Lib "Cocoa" Selector "respondsToSelector:" (obj As Ptr, sel As Ptr) As Boolean
// verses
Declare Function respondsToSelector Lib "Foundation" Selector "respondsToSelector:" (obj As Ptr, sel As Ptr) As Boolean
Note: This post is about expanding my knowledge of Declare, and not about finding a Plugin solution (I already own both MBS & Einhugur).
Figure 1-1 in the Cocoa Fundamental Guide will probably explain this best. Long and short of this is that Foundation is lower in the stack and is the floor that everything else is based upon. Think of it as the non-UI or console type frameworks whereas Cocoa is higher level, built upon Foundation and includes the GUI frameworks. Cocoa itself, traditionally is just macOS with AppKit, whereas CocoaTouch is synonymous but for iOS and with UIKit.
Specifically to your questions…
1 & 2: The respondsToSelector is likely in Foundation hence why referencing Foundation or Cocoa works (e.g. Cocoa is built upon Foundation and hence has access to the framework).
3: No, it should only exist in one or the other.
4: There might be a theoretical performance delta in going directly to the source framework versus through another one, but for all practical purposes, in my experience it doesn’t really matter.
You won’t need to worry about the library name 99.99% of the time. The only time it will matter is if the OS can’t figure out which library to use on its own and I’ve only ever encountered one or two.
The reality is that the selector is sent to the object that’s passed to the first parameter and if it isn’t right, it’ll just crash anyway.
That said, go look at this repo
There’s an assistant in there just for macOS declares and if you switch the Apple docs over to objective-c, it’s almost copy & paste. You copy the function definition from apples doc page and then in the Xojo code editor, you right-click and select Code Assistants > Convert > macOS & iOS Declare Maker. You may still need to do some cleanup, but it gets the basic structure for you and puts a copy of the original text there as a comment for you.
Keeping in mind, a Selector (if there is one) can be a single word (sometimes followed by a trailing colon:) or multiple words delimited by colons, e.g., getRed:green:blue:alpha:
Is it then fair to say, that the Selector value acts as a “sort of” global identifier for the function and/or property that’s being called within Cocoa?
Or global at least given the context of the object or control being referenced, e.g., NSButton or NSAlert?
Already downloaded and installed I’ve been using it to help verify some of my assumptions as well as to replace some External Methods.
Works great, although sometimes (only rarely) it doesn’t always produce a result. I don’t know if you’re open to feedback if I find something the script doesn’t like? Please let me know.
I think you’re in the ballpark of your thinking except for the global part. I’m not a super expert in declares, but using the “Soft Declare” example from the Xojo Examples and in particular the MiniaturizeButton.Depressed event as an example you’ll find:
Soft Declare Sub miniaturize Lib "Cocoa" selector "miniaturize:" (windowRef As Ptr, id As Ptr)
If you look at the Apple docs for NSWindow, you’ll find that miniaturize is simply a function (aka method in Xojo-land) for the windowRef (aka NSWindow).
So tightening things up a bit, things aren’t really global, but you’re messaging to NSWindows to run the miniaturize function is similar to how say one might call the Minimize method on DesktopWindow within Xojo. And you’re able to get to NSWindow as you’re using the Cocoa library, of which NSWindow is a part of.
windowRef is the handle that points to the underlying NSWindow of DesktopWindow by way of the Handle property.
miniaturize: is the method being called, but the only time they end in a : is if a parameter is being passed.
The Cocoa library isn’t used hardly ever in Xojo declares if the object (NSWindow) “responds to” the message(miniaturize:), unless there is some sort of conflict. It must however point to something valid.
Note that in my tool, they all say “Foundation” and you’ll be hard pressed to find one that doesn’t work.
Ah , so the Selector is in context (unique?) to the object reference (Handle/Ptr) that is messaged by way of the first parameter? I should have realized that. Thank you.
Together with your comment and Patrick’s, this is so obvious now.
I suppose that means the Handle/Ptr is read first, to get the object “type” (e.g., NSWindow), before evaluating the Selector? And as long as the called Library understands both object type and Selector - we’re good to go?
That was one of my assumptions, thank you for confirming.
That is interesting. The macOSLib repo uses “Cocoa” almost everywhere, whereas Sam’s AppKit has all his External Methods broken out in just about all the various Libraries such as AppKit, Foundation, CoreFoundation, several graphic specific Libs, etc. But maybe that’s also for organization purposes (there’s a lot of code in there).