objc

Exposes native Objective-C classes.

Native Classes

To access a native Objective-C class, append its name to objc.

-- access the UIScreen class
UIScreen = objc.UIScreen

Constructor

If the native class has a new constructor, you can invoke it directly instead of calling the new method.

-- create an instance of NSDateComponents
dateComponents = objc.NSDateComponents()

Properties

Properties can be read and modified directly.

-- read the screen brightness
brightness = objc.UIScreen.mainScreen.brightness

-- change the screen brightness
objc.UIScreen.mainScreen.brightness = 0.5

Methods

Methods are invoked using the ‘:’ operator and their full selector name, including named arguments separated by underscores ‘_’ instead of colons. Note that the Objective-C method names must always end with an underscore in Codea. The underscores are required for Codea to find the corresponding signatures in Objective-C.

-- Calling a method with multiple arguments
controller:presentViewController_animated_completion_(newController, true, nil)

-- Calling a method with no argument
webView:goBack_()

Callbacks

Callbacks such as completion handlers with up to 7 arguments are supported by passing a function where each parameter is prefixed to indicate the corresponding native type.

The following prefixes are supported for callback arguments:

  • c: char

  • i: int, NSInteger

  • uc: unsigned char

  • ui: unsigned int, NSUInteger

  • f: float

  • d: double, CGFloat

  • b: bool, BOOL

  • s: char*

  • o: NSObject, NSString, etc.

Note that only the first one or two characters are important in your argument names. bGranted and boolGranted will both work for a boolean argument, but for our examples, we decided to go with the second option.

Struct members are passed separately. For example, for an NSRange argument, you could use intLocation and intLength arguments.

Pointers for value types are also supported by prefixing them with p, (e.g. pboolStop). The actual value can be accessed and modified using .value.

Note that when using objc from within a callback, changes are not guaranteed to occur on the main thread. Consider using objc.async inside your callback if you need changes to happen on the main thread, such as modifying UIControls.

Automatic Conversions

Some Codea types will be converted to corresponding Objective types automatically when passed to native methods or properties.

  • color: UIColor

  • vec2: CGPoint

--- uiView: objc.UIView
uiView.backgroundColor = Color(255, 0, 0)

--- uiTextView: objc.UITextView
uiTextView:setContentOffset_(vec2(0, 100))

Examples

Change the screen brightness to 50%
objc.UIScreen.mainScreen.brightness = 0.5
Request application review
scene = objc.app.keyWindow.windowScene
store = objc.SKStoreReviewController
store:requestReviewInScene_(scene)
Request notifications permission
center = objc.
    UNUserNotificationCenter.
    currentNotificationCenter
options = objc.enum.UNAuthorizationOptions
center:requestAuthorizationWithOptions_completionHandler_(
    options.badge | options.sound | options.alert,
    function(boolGranted, objError)
    if boolGranted then
        print("granted")
    elseif objError then
        print("error " .. objError.code)
    end
    end)
Enumerate words until the word stop is found
txt = "First second stop third fourth"
str = objc.string(txt)
str:enumerateSubstringsInRange_options_usingBlock_(
    objc.range(0, txt:len()),
    objc.enum.NSStringEnumerationOptions.byWords,
    function(objWord,
            isubstringLocation,
            iSubstringLength,
            iEnclosingLocation,
            iEnclosingLength,
            pboolStop)
        if objWord == "stop" then
            pboolStop.value = true
        else
            print(objWord)
        end
    end)
objc.delegate(name)

Returns a type which can be instantiated and used as an Objective-C delegate for the specified type.

Parameters:

name (string) – The name of the delegate.

Returns:

A type to be used as an Objective-C delegate.

Return type:

table

Syntax:
objc.delegate("DelegateName")
UITextViewDelegate Example
Delegate = objc.delegate("UITextViewDelegate")

function Delegate:textViewShouldBeginEditing_(objTextView)
    -- replace with false to prevent editing
    return true
end

function Delegate:textViewDidChange_(objTextView)
    print(objTextView.text)
end

-- uiTextView.delegate = Delegate()
WKScriptMessageHandler Example
-- Exposes the following method to JavaScript:
-- window.webkit.messageHandlers.log.postMessage
Handler = objc.delegate("WKScriptMessageHandler")

function Handler:
    userContentController_didReceiveScriptMessage_(
    objUserContentController, objMessage)
    print(objMessage.body)
end

function setup()
    local ctrl = objc.WKUserContentController()
    local logHandler = Handler()
    ctrl:addScriptMessageHandler_name_(
    logHandler, "log")
end
objc.class(name)

Returns a type which can be instantiated and used as an Objective-C class, for example combined with a selector when registering for notifications through the NSNotificationCenter.

Parameters:

name (string) – The name of the class.

Returns:

A type to be used as an Objective-C class.

Return type:

table

Syntax:
objc.class("ClassName")
NotificationHandler Example
NotificationHandler = objc.class("NotificationHandler")

function NotificationHandler:textDidChange(objNotification)
    print(objNotification.object.text)
end

handler = NotificationHandler()

notificationCenter = objc.NSNotificationCenter.defaultCenter
notificationCenter:addObserver_selector_name_object_(
    handler,
    objc.selector("textDidChange"),
    "UITextViewTextDidChangeNotification",
    nil)
objc.selector(name)

Returns an Objective-C selector with the specified name which can be used in combination with an objc.class, for example to register for notifications through the NSNotificationCenter.

Parameters:

name (string) – The name of the selector.

Returns:

An Objective-C selector (or SEL).

Return type:

table

Syntax:
objc.selector("SelectorName")
NotificationHandler Example
NotificationHandler = objc.class("NotificationHandler")

function NotificationHandler:textDidChange(objNotification)
    print(objNotification.object.text)
end

handler = NotificationHandler()

notificationCenter = objc.NSNotificationCenter.defaultCenter
notificationCenter:addObserver_selector_name_object_(
    handler,
    objc.selector("textDidChange"),
    "UITextViewTextDidChangeNotification",
    nil)
objc.set(table)

Returns an Objective-C NSSet initialized from a Lua table.

By default, NSSet returned from calls to Objective-C (or reading properties) are automatically converted to Lua tables. If you need to use the NSSet, you can convert the table to NSSet using objc.set.

Parameters:

table (table) – A Lua table.

Returns:

An Objective-C NSSet.

Return type:

table

Syntax:
objc.set({1, 2, 3})
objc.string(text)

Returns an Objective-C NSString initialized from a Lua string.

By default, strings returned from calls to Objective-C (or reading properties) are automatically converted to Lua strings and vice versa. If you need to access NSString methods, you can convert the strings to NSString using objc.string.

Parameters:

text (string) – The text to convert to an NSString.

Returns:

An Objective-C NSString.

Return type:

table

Syntax:
objc.string("Text")
enum: table

Exposes native Objective-C enumerations.

When value names are prefixed with their enumeration’s name, the prefix is removed to simplify their usage.

For example, objc.enum.NLTokenUnit.paragraph is the integer value for NLTokenUnitParagraph (2).

Unnamed enum values can be found directly under objc.enum, e.g. objc.enum.NSUTF8StringEncoding.

Returns:

A table containing native enumerations and their values.

Return type:

table

Syntax:
objc.enum.EnumName.ValueName
Combine UNAuthorizationOptions
opts =
    objc.enum.UNAuthorizationOptions.badge |
    objc.enum.UNAuthorizationOptions.sound |
    objc.enum.UNAuthorizationOptions.alert
app: table

The UIApplication’s sharedApplication.

Returns:

The UIApplication’s sharedApplication.

Return type:

table

viewer: table

The runtime UIViewController.

Returns:

The runtime UIViewController.

Return type:

table

info: table

Exposes the info dictionary keys and values.

For better readability, all keys have their Apple prefix removed.

For example, to get the value of NSBundleIdentifier, use objc.info.bundleIdentifier.

Returns:

A table containing the info dictionary keys and values.

Return type:

table

Test if running in an exported project
isStandalone = objc.info.bundleIdentifier ~= "com.twolivesleft.Codify"
insets: table

Create a UIEdgeInsets.

Parameters:
  • top (number) – top value of the UIEdgeInsets

  • left (number) – left value of the UIEdgeInsets

  • bottom (number) – bottom value of the UIEdgeInsets

  • right (number) – right value of the UIEdgeInsets

Returns:

The UIEdgeInsets struct.

Return type:

table

Syntax:
objc.insets(top, left, bottom, right)
objc.log(message)

Log a message using NSLog instead of the Codea console.

Parameters:

message (string) – Message to display.

Syntax:
objc.log(message)
objc.inspect(class)

Inspect an Objective-C class, listing its variables, properties, methods and protocols.

Returns a table with the following information:

  • super: the superclass which can be used as if it was accessed through objc

  • variables: array of instance variables

    • name: name of the variable

    • typeEncoding: see Type Encoding

    • type: user-friendly name of the variable type

  • properties: array of instance properties

    • name: name of the property

    • attributes: see Property Type String

    • type: user-friendly name of the property type

  • methods: array of instance methods

    • name: name of the methods

    • returnType: user-friendly name of the method’s return type

    • arguments: array of method arguments

      • name: name of the arguments

      • typeEncoding: see Type Encoding

      • type: user-friendly name of the argument’s type

  • protocols: array of instance protocols

    • name: name of the protocol

Class members are accessible by prefixing with class., for example using objc.inspect(myClass).class.variables to list the class variables of myClass.

Parameters:

class (table) – Objective-C class to inspect.

Returns:

A table with the class information

Return type:

table

Syntax:
objc.inspect(class)
Inspect the SFSpeechRecognizer class
inspect = objc.inspect(objc.SFSpeechRecognizer)
print("Class has " .. #inspect.methods .. " instance methods.")
objc.async(function)

Calls the function parameter on the main thread asynchronously.

Parameters:

function (function) – Parameterless function to run on the main thread.

Syntax:
objc.async(someFunction)
Run a function on the main thread
objc.async(function()
    print("This will run on the main thread.")
end)
objc.point(x, y)

Create a CGPoint.

Parameters:
  • x (number) – x position of the CGPoint

  • y (number) – y position of the CGPoint

Returns:

The CGPoint struct.

Return type:

table

Syntax:
objc.point(x, y)
Create a CGPoint
point = objc.point(100, 200)
objc.rect(x, y, width, height)

Create a CGRect.

Parameters:
  • x (number) – x position of the CGRect

  • y (number) – y position of the CGRect

  • width (number) – width of the CGRect

  • height (number) – height of the CGRect

Returns:

The CGRect struct.

Return type:

table

Syntax:
objc.rect(x, y, width, height)
Create a CGRect
rect = objc.rect(100, 200, 300, 400)
objc.size(width, height)

Create a CGSize.

Parameters:
  • width (number) – width of the CGSize

  • height (number) – height of the CGSize

Returns:

The CGSize struct.

Return type:

table

Syntax:
objc.size(width, height)
Create a CGSize
size = objc.size(300, 400)
objc.range(loc, len)

Create a NSRange.

Parameters:
  • loc (number) – location of the NSRange

  • len (number) – length of the NSRange

Returns:

The NSRange struct.

Return type:

table

Syntax:
objc.range(loc, len)
Create a NSRange
range = objc.range(10, 20)
objc.color(r, g, b, a)

Create a CGColor. For UIColor, use the Codea Color type instead.

Parameters:
  • r (number) – red value of the CGColor

  • g (number) – green value of the CGColor

  • b (number) – blue value of the CGColor

  • a (number) – alpha value of the CGColor

Returns:

The CGColor struct.

Return type:

table

Syntax:
objc.color(r, g, b, a)
Create a CGColor
color = objc.color(1, 0, 0, 1)
objc.vector(dx, dy)

Create a CGVector.

Parameters:
  • dx (number) – x direction of the CGVector

  • dy (number) – y direction of the CGVector

Returns:

The CGVector struct.

Return type:

table

Syntax:
objc.vector(dx, dy)
Create a CGVector
vector = objc.vector(1, 0)
objc.affineTransform()

Create a CGAffineTransform.

Parameters:
  • a (number) – a value of the CGAffineTransform

  • b (number) – b value of the CGAffineTransform

  • c (number) – c value of the CGAffineTransform

  • d (number) – d value of the CGAffineTransform

  • tx (number) – tx value of the CGAffineTransform

  • ty (number) – ty value of the CGAffineTransform

Returns:

The CGAffineTransform struct.

Return type:

table

Syntax:
objc.affineTransform(a, b, c, d, tx, ty)
Create a CGAffineTransform
affineTransform = objc.affineTransform(1, 0, 0, 1, 100, 200)

Frameworks

Here are some of the frameworks included with the Codea runtime.

Refer to Apple’s documentation for how to interact with them.

For a more exhaustive list, use the example code below.

List all included system Frameworks
-- list all included system Frameworks
local bundles = objc.NSBundle.allFrameworks
local systemBundles = {}

for i, b in ipairs(bundles) do
    if string.find(
        b.bundlePath,
        "System/Library/Frameworks/") then
        table.insert(systemBundles, b.bundlePath)
    end
end

table.sort(systemBundles)

for i, bundle in ipairs(systemBundles) do
    print(bundle)
end