# Calling native macOS APIs

You can call into Cocoa APIs to use methods and properties that are not built into the framework by using the `Declare</api/language/declare>` command. To create a Declare statement you first need to track down the API you want to use using Apple's documentation: [Apple Developer Documentation](https://developer.apple.com/documentation/). Most of the time you will reference the [Foundation](https://developer.apple.com/documentation/foundation) and [AppKit](https://developer.apple.com/documentation/appkit) libraries, but there are many other libraries as well. Xojo Declares use the Objective-C names so be sure to refer to those in the documentation rather than the Swift naming.

When you call Cocoa methods you supply the method name using the Selector part of the Declare command. The selector name has to end in a ":" if there are any parameters that are passed, an oddity of how Objective-C works. Unlike with Xojo methods, the case of the name also has to match exactly. For the Xojo Declare, the **first parameter is always required and must be a reference to the class containing the method you are calling**.

## Center a window

To start with a simple example, consider that you may to center a window on the screen. You can obviously do this by manually adjusting the window's Top and Left properties by taking into account the window size and the screen size, but Cocoa has a simple center function that can be used on a window.

On macOS, a Xojo window is actually a native NSWindow. When you view Apple's [docs for NSWindow](https://developer.apple.com/documentation/appkit/nswindow) you'll see there is a [center](https://developer.apple.com/documentation/appkit/nswindow/1419090-center) method. This method is very simple as it does not take any parameters. Looking at the doc page you should note that this function is in the AppKit library. Now you can create a Declare command to map to the center method:

``` xojo
Declare Sub centerWindow Lib "AppKit" Selector "center" (windowHandle As Ptr)
```

Remember, even though the center method does not take any parameters, you still have to add a parameter to the Declare so you can pass in the reference to the calling class, which in this case is the window to center.

You can call this method like this (such as from a button's Pressed event handler):

``` xojo
centerWindow(Self.Handle)
```

Because this method is called for a window, you can put it in a Xojo Extension Method to make it easier to call. To do this, create a global method on a module like this:

``` xojo
Public Sub Center(Extends w As DesktopWindow)
  #If TargetMacOS Then
    Declare Sub centerWindow Lib "AppKit" Selector "center" (windowHandle As Ptr)
    centerWindow(w.Handle)
  #EndIf
End Sub
```

Note the use of the "#If TargetMacOS" line. This prevents this code from being compiled into Windows or Linux builds of your app where the code could possible crash your app.

This now allows you to have code like this on a window's Opening event to center the window:

``` xojo
Self.Center
```

## Display the standard About window

Instead of manually creating a modal window to display the About window for your app, you can instead display the standard macOS About Window. This window has a fixed size, gets the app name directly from the built app name, the icon from the app icon and the version from the version values in Shared Build Settings. On the [NSApplication](https://developer.apple.com/documentation/appkit/nsapplication?language=objc) class there is a method called [orderFrontStandardAboutPanel](https://developer.apple.com/documentation/appkit/nsapplication/1428724-orderfrontstandardaboutpanel?language=objc) that displays this standard about window.

The first thing you need to do is to get a reference to the shared application. Xojo does not provide this for you so you'll have to use some Declares to get at it.

To get started, in Xojo create a public method on the App object and call it ShowAbout.

The first bit of code you need has to get a reference to the NSApplication class and then call the sharedApplication method to get an instance of the app. In order to do this, you'll need to use a common utility function, NSClassFromString, that gets a reference to a Cocoa class. So this is the first line of code:

``` xojo
Declare Function NSClassFromString Lib "AppKit" (className As CFStringRef) As Ptr
```

You can now use this function to get a reference to the NSApplication class:

``` xojo
Var nsApp As Ptr = NSClassFromString("NSApplication")
```

Next you can use this to call the sharedApplication method on NSApplication with this Declare:

``` xojo
Declare Function SharedApplication Lib "AppKit" Selector "sharedApplication" (receiver As Ptr) As Ptr
Var sharedApp As Ptr = SharedApplication(nsApp)
```

You now have the reference to the app in the sharedApp variable. The last thing to do is to call the orderFrontStandardAboutPanel method, which has this Objective-C declaration in the Apple docs:

``` xojo
(void)orderFrontStandardAboutPanel:(id)sender;
```

This tells you it is a Sub (the void at the beginning means it does not return a value) and that it takes one parameter. So the Declare looks like this:

``` xojo
Declare Sub OrderFrontStandardAboutPanel Lib "AppKit" Selector "orderFrontStandardAboutPanel:" (sharedApp As Ptr, ID As Ptr)
```

And lastly you can call this method like this (a value for the ID parameter is not actually needed):

``` xojo
OrderFrontStandardAboutPanel(sharedApp, Nil)
```

Combining all this code together results in this:

``` xojo
Public Sub ShowAbout()
  #If TargetMacOS Then
    Declare Function NSClassFromString Lib "AppKit" (className As CFStringRef) As Ptr
    Var nsApp As Ptr = NSClassFromString("NSApplication")

    Declare Function SharedApplication Lib "AppKit" Selector "sharedApplication" (receiver As Ptr) As Ptr
    Var sharedApp As Ptr = SharedApplication(nsApp)

    Declare Sub OrderFrontStandardAboutPanel Lib "AppKit" Selector "orderFrontStandardAboutPanel:" (sharedApp As Ptr, ID As Ptr)
    OrderFrontStandardAboutPanel(sharedApp, Nil)
  #EndIf
End Sub
```

As above, note the use of the "#If TargetMacOS" line which prevents this code from being compiled into Windows or Linux builds of your app where the code could possibly crash your app.

You can now display the about window with this code:

``` xojo
App.ShowAbout
```

## 64-bit information

Some API calls need to adapt when used in a 64-bit app. For example, some API calls expect an Int32 in an 32-bit app but want an Int64 in a 64-bit app. If you have hard-coded usage of Int32 in your Declare API calls then you'll have to fix them so that they work for 64-bit. For Int32/Int64 you should just use the `Integer</api/data_types/integer>` type which will automatically use the correct type for the type of the app.

You may run into a similar issue with floating point where Single is used in 32-bit apps, but Double is used for 64-bit apps. In these cases use the `CGFloat</api/data_types/additional_types/cgfloat>` type to have it automatically choose the correct type.

<div id="/topics/declares/calling_native_macos_apis/see_also">

<div class="seealso">

- `Declare</api/language/declare>` keyword
- `macOS Declare Samples</topics/declares/examples_for_macos>`
- [Using Declares in Your Desktop Apps](https://blog.xojo.com/2014/09/15/using-declares-in-your-multi-platform-desktop-apps/)
- [macoslib](https://github.com/macoslib/macoslib) open-source project

</div>

</div>
