diff --git a/Makefile b/Makefile
index fdfdc7c8f4cf36e68f8bb2a1352a79c24d080c19..483c0aa49a6ea0484ef722b8dd0b84869db18c28 100644
--- a/Makefile
+++ b/Makefile
@@ -5,7 +5,7 @@ else ifeq ($(shell uname -s),Linux)
 	TRAY_CFLAGS := -DTRAY_APPINDICATOR=1 $(shell pkg-config --cflags appindicator3-0.1)
 	TRAY_LDFLAGS := $(shell pkg-config --libs appindicator3-0.1)
 else ifeq ($(shell uname -s),Darwin)
-	TRAY_CFLAGS := -DTRAY_APPKIT=1 -x objective-c
+	TRAY_CFLAGS := -DTRAY_APPKIT=1
 	TRAY_LDFLAGS := -framework Cocoa
 endif
 
diff --git a/README.md b/README.md
index d57b48e01e3391d35f6d298e2de0614205b0c882..1ec6d2356e48316ee1576bf28ae15371ecca116e 100644
--- a/README.md
+++ b/README.md
@@ -136,7 +136,7 @@ array must have text field set to NULL.
 * [x] Checked/unchecked menu items
 * [x] Nested menus
 * [ ] Icons for menu items
-* [ ] Rewrite ObjC code in C using ObjC Runtime (now ObjC code breaks many linters and static analyzers)
+* [x] Rewrite ObjC code in C using ObjC Runtime (now ObjC code breaks many linters and static analyzers)
 * [ ] Call GTK code using dlopen/dlsym (to make binaries run safely if Gtk libraries are not available)
 
 ## License
diff --git a/tray.h b/tray.h
index 89b313d4dbbcfce74bb13ed6461f71e4c7b44036..fac1739054a5828a6fd30f0b83b2e2fc14603871 100644
--- a/tray.h
+++ b/tray.h
@@ -90,92 +90,118 @@ static void tray_exit() { loop_result = -1; }
 
 #elif defined(TRAY_APPKIT)
 
-#import <Cocoa/Cocoa.h>
+#include <objc/objc-runtime.h>
+#include <limits.h>
 
-static NSAutoreleasePool *pool;
-static NSStatusBar *statusBar;
+static id app;
+static id pool;
+static id statusBar;
 static id statusItem;
 static id statusBarButton;
 
-@interface Tray : NSObject <NSApplicationDelegate>
-- (void)menuCallback:(id)sender;
-@end
-@implementation Tray
-- (void)menuCallback:(id)sender {
-  struct tray_menu *m =
-      (struct tray_menu *)[[sender representedObject] pointerValue];
-  if (m != NULL && m->cb != NULL) {
-    m->cb(m);
-  }
-}
-@end
-
-static NSMenu *_tray_menu(struct tray_menu *m) {
-  NSMenu *menu = [NSMenu new];
-  [menu autorelease];
-  [menu setAutoenablesItems:NO];
-  for (; m != NULL && m->text != NULL; m++) {
-    if (strcmp(m->text, "-") == 0) {
-      [menu addItem:[NSMenuItem separatorItem]];
-    } else {
-      NSMenuItem *menuItem = [NSMenuItem alloc];
-      [menuItem autorelease];
-      [menuItem initWithTitle:[NSString stringWithUTF8String:m->text]
-                       action:@selector(menuCallback:)
-                keyEquivalent:@""];
-      [menuItem setEnabled:(m->disabled ? NO : YES)];
-      [menuItem setState:(m->checked ? NSOnState : NSOffState)];
-      [menuItem setRepresentedObject:[NSValue valueWithPointer:m]];
-
-      [menu addItem:menuItem];
+static id _tray_menu(struct tray_menu *m) {
+    id menu = objc_msgSend((id)objc_getClass("NSMenu"), sel_registerName("new"));
+    objc_msgSend(menu, sel_registerName("autorelease"));
+    objc_msgSend(menu, sel_registerName("setAutoenablesItems:"), false);
 
-      if (m->submenu != NULL) {
-        [menu setSubmenu:_tray_menu(m->submenu) forItem:menuItem];
+    for (; m != NULL && m->text != NULL; m++) {
+      if (strcmp(m->text, "-") == 0) {
+        objc_msgSend(menu, sel_registerName("addItem:"), 
+          objc_msgSend((id)objc_getClass("NSMenuItem"), sel_registerName("separatorItem")));
+      } else {
+        id menuItem = objc_msgSend((id)objc_getClass("NSMenuItem"), sel_registerName("alloc"));
+        objc_msgSend(menuItem, sel_registerName("autorelease"));
+        objc_msgSend(menuItem, sel_registerName("initWithTitle:action:keyEquivalent:"),
+                  objc_msgSend((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), m->text),
+                  sel_registerName("menuCallback:"),
+                  objc_msgSend((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), ""));
+  
+        objc_msgSend(menuItem, sel_registerName("setEnabled:"), (m->disabled ? false : true));
+          objc_msgSend(menuItem, sel_registerName("setState:"), (m->checked ? 1 : 0));
+          objc_msgSend(menuItem, sel_registerName("setRepresentedObject:"),
+            objc_msgSend((id)objc_getClass("NSValue"), sel_registerName("valueWithPointer:"), m));
+  
+          objc_msgSend(menu, sel_registerName("addItem:"), menuItem);
+  
+          if (m->submenu != NULL) {
+            objc_msgSend(menu, sel_registerName("setSubmenu:forItem:"), _tray_menu(m->submenu), menuItem);
       }
     }
   }
+
   return menu;
 }
 
-static int tray_init(struct tray *tray) {
-  pool = [NSAutoreleasePool new];
-  [NSApplication sharedApplication];
-
-  Tray *trayDelegate = [Tray new];
-  [NSApp setDelegate:trayDelegate];
+static void menu_callback(id self, SEL cmd, id sender) {
+  struct tray_menu *m =
+      (struct tray_menu *)objc_msgSend(objc_msgSend(sender, sel_registerName("representedObject")), 
+                  sel_registerName("pointerValue"));
 
-  statusBar = [NSStatusBar systemStatusBar];
-  statusItem = [statusBar statusItemWithLength:NSVariableStatusItemLength];
-  [statusItem retain];
-  [statusItem setHighlightMode:YES];
-  statusBarButton = [statusItem button];
+    if (m != NULL && m->cb != NULL) {
+      m->cb(m);
+    }
+}
 
-  tray_update(tray);
-  [NSApp activateIgnoringOtherApps:YES];
-  return 0;
+static int tray_init(struct tray *tray) {
+    pool = objc_msgSend((id)objc_getClass("NSAutoreleasePool"),
+                          sel_registerName("new"));
+  
+    objc_msgSend((id)objc_getClass("NSApplication"),
+                          sel_registerName("sharedApplication"));
+  
+    Class trayDelegateClass = objc_allocateClassPair(objc_getClass("NSObject"), "Tray", 0);
+    class_addProtocol(trayDelegateClass, objc_getProtocol("NSApplicationDelegate"));
+    class_addMethod(trayDelegateClass, sel_registerName("menuCallback:"), (IMP)menu_callback, "v@:@");
+    objc_registerClassPair(trayDelegateClass);
+  
+    id trayDelegate = objc_msgSend((id)trayDelegateClass,
+                          sel_registerName("new"));
+  
+    app = objc_msgSend((id)objc_getClass("NSApplication"),
+                          sel_registerName("sharedApplication"));
+  
+    objc_msgSend(app, sel_registerName("setDelegate:"), trayDelegate);
+  
+    statusBar = objc_msgSend((id)objc_getClass("NSStatusBar"),
+                          sel_registerName("systemStatusBar"));
+  
+    statusItem = objc_msgSend(statusBar, sel_registerName("statusItemWithLength:"), -1.0);
+  
+    objc_msgSend(statusItem, sel_registerName("retain"));
+    objc_msgSend(statusItem, sel_registerName("setHighlightMode:"), true);
+    statusBarButton = objc_msgSend(statusItem, sel_registerName("button"));
+    tray_update(tray);
+    objc_msgSend(app, sel_registerName("activateIgnoringOtherApps:"), true);
+    return 0;
 }
 
 static int tray_loop(int blocking) {
-  NSEvent *event;
-  NSDate *until = (blocking ? [NSDate distantFuture] : [NSDate distantPast]);
-  event = [NSApp nextEventMatchingMask:NSAnyEventMask
-                             untilDate:until
-                                inMode:NSDefaultRunLoopMode
-                               dequeue:YES];
-  if (event) {
-    [NSApp sendEvent:event];
-  }
-  return 0;
+    id until = (blocking ? 
+      objc_msgSend((id)objc_getClass("NSDate"), sel_registerName("distantFuture")) : 
+      objc_msgSend((id)objc_getClass("NSDate"), sel_registerName("distantPast")));
+  
+    id event = objc_msgSend(app, sel_registerName("nextEventMatchingMask:untilDate:inMode:dequeue:"), 
+                ULONG_MAX, 
+                until, 
+                objc_msgSend((id)objc_getClass("NSString"), 
+                  sel_registerName("stringWithUTF8String:"), 
+                  "kCFRunLoopDefaultMode"), 
+                true);
+    if (event) {
+      objc_msgSend(app, sel_registerName("sendEvent:"), event);
+    }
+    return 0;
 }
 
 static void tray_update(struct tray *tray) {
-  [statusBarButton
-      setImage:[NSImage imageNamed:[NSString stringWithUTF8String:tray->icon]]];
+  objc_msgSend(statusBarButton, sel_registerName("setImage:"), 
+    objc_msgSend((id)objc_getClass("NSImage"), sel_registerName("imageNamed:"), 
+      objc_msgSend((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), tray->icon)));
 
-  [statusItem setMenu:_tray_menu(tray->menu)];
+  objc_msgSend(statusItem, sel_registerName("setMenu:"), _tray_menu(tray->menu));
 }
 
-static void tray_exit() { [NSApp terminate:NSApp]; }
+static void tray_exit() { objc_msgSend(app, sel_registerName("terminate:"), app); }
 
 #elif defined(TRAY_WINAPI)
 #include <windows.h>