# zig-objc - Objective-C Runtime Bindings for Zig

zig-objc allows Zig to call Objective-C using the macOS
[Objective-C runtime](https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc).

**Project Status:** This library does not currently have 100% coverage over the Objective-C
runtime, but supports enough features to be useful. I use this library in
shipping code that I run every day.

## Features

  * Classes:
    - Find classes
    - Read property metadata
    - Call methods
  * Objects:
    - Class or class name for object
    - Read and write properties
    - Call methods
  * Autorelease pools

There is still a bunch of the runtime API that isn't supported. It wouldn't
be hard work to add it, I just haven't needed it. For example: object
instance variables, protocols, dynamically registering new classes, etc.

Feel free to open a pull request if you want additional features.
**Do not open issues to request features (only pull requests).** I'm
only going to add features I need, _unless_ you open a pull request to
add it yourself.

## Example

Here is an example that uses `NSProcessInfo` to implement a function
`macosVersionAtLeast` that returns true if the running macOS versions
is at least the given arguments.

```zig
const objc = @import("objc");

pub fn macosVersionAtLeast(major: i64, minor: i64, patch: i64) bool {
    /// Get the objc class from the runtime
    const NSProcessInfo = objc.Class.getClass("NSProcessInfo").?;

    /// Call a class method with no arguments that returns another objc object.
    const info = NSProcessInfo.msgSend(objc.Object, objc.sel("processInfo"), .{});

    /// Call an instance method that returns a boolean and takes a single
    /// argument.
    return info.msgSend(bool, objc.sel("isOperatingSystemAtLeastVersion:"), .{
        NSOperatingSystemVersion{ .major = major, .minor = minor, .patch = patch },
    });
}

/// This extern struct matches the Cocoa headers for layout.
const NSOperatingSystemVersion = extern struct {
    major: i64,
    minor: i64,
    patch: i64,
};
```

## Usage

**Warning:** This project follows the nightly releases of Zig and may
not work with released versions of Zig until Zig stabilizes. I also
am **not promising API stability** right now.

Use your favorite Zig package manager or vendor this repository, then add the package.
For example in your build.zig:

```zig
const objc = @import("vendor/zig-objc/build.zig");

pub fn build(b: *std.build.Builder) !void {
  // ... other stuff

  exe.addPackage(objc.pkg);
}
```

## Documentation

Read the source code, it is well commented. If something isn't clear, please
open an issue and I'll enhance the source code. Some familiarity with
Objective-C concepts is expected for understanding the doc comments.