This vlang package provides Objective-C Runtime bindings for V.
It is currently work in progress and should be considered experimental. It's tested on x86_64 and arm64 (Apple Silicon) architectures, macOS Sonoma 14.5.
Supported features:
- Bool type
- Id type
- Load classes
- Create instances
- Register selectors
- Send messages (varargs are not supported)
- Class declaration
v install magic003.objcThe Bool type is an alias of the V bool type.
assert objc.yes == true
assert objc.no == falseAn Objective-C class can be loaded using either a factory function or a static type method.
cls1 := objc.Class.get('NSMutableArray') or { panic('failed to load class NSMutableArray') }
cls2 := objc.class('NSMutableArray') or { panic('failed to load class NSMutableArray') }An Objective-C selector can be registered using either a factory function or a static type method.
s1 := objc.Sel.get('init')
s2 := objc.sel('init')Messages can be sent to a class or an instance. There are two types of messages:
- request[R](): a message with return type- R.
- notify(): a message without a return value.
unsafe {
    // a mutable array instance is created via chained messages
    arr := cls1.message(objc.sel('alloc')).request[objc.Id]()
            .message(objc.sel('init')).request[objc.Id]()
    // load the NSObject class and create an instance
    obj_cls := objc.class('NSObject') or { panic('failed to load class NSObject') }
    obj := obj_cls.message(sel('new')).request[objc.Id]()
    // add an object to the array. Message with one argument and no return value. 
    // Use `args2()`, `args3()` and etc for more arguments.
    arr.message(sel('addObject:')).args1(obj).notify()
    // message without an argument.
    size := arr.message(sel('count')).request[u64]()
    assert size == 1
}New classes can be declared and registered with the Objective-C Runtime.
superclass := objc.class('NSObject') or { panic('failed to load class NSObject') }
// create a new class with `NSObject` as the super class.
decl := ClassDecl.new(superclass, 'NewClass', 0) or {
    panic('failed to create class NewClass')
}
// add ivars
decl.add_ivar[i64]('num')
decl.add_ivar[objc.Id]('obj')
// add methods
m1 := objc.void_method_1[bool](fn (self objc.Id, cmd objc.Sel, flag bool) {
    // do something
})
unsafe { decl.add_method(objc.sel('method1:'), m1) }
m2 := objc.method_1[int, objc.Id](fn (self objc.Id, cmd objc.Sel, obj objc.Id) int {
    return 10
})
unsafe { delc.add_method(objc.sel('method2:'), m2) }
// register the class
cls := decl.register()
unsafe {
    // create an instance from the new class
    obj := cls.message(objc.sel('new')).request[objc.Id]()
    
    // set ivar
    obj.set_ivar('num', 1)
    // call method
    obj.message(objc.sel('method1:')).args1(true).notify()
}The unit tests have basic usages.
Check out the examples folder for more examples.
- API Documentation: http://magic003.github.io/objc
- Why this project: V and Objective-C interoperability
- Programming with Objective-C
- Objective-C Runtime APIs
- rust-objc: Objective-C bindings for Rust.