diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index db1da771a..1d52c7516 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -34,7 +34,7 @@ jobs:
     - name: Install toolchain
       uses: actions-rs/toolchain@v1
       with:
-        toolchain: 1.56.1
+        toolchain: '1.60'
         override: true
     - name: Build
       run: cargo build --verbose
diff --git a/cocoa-foundation/Cargo.toml b/cocoa-foundation/Cargo.toml
index d6e99aff1..01bd3d42f 100644
--- a/cocoa-foundation/Cargo.toml
+++ b/cocoa-foundation/Cargo.toml
@@ -12,9 +12,9 @@ license = "MIT OR Apache-2.0"
 default-target = "x86_64-apple-darwin"
 
 [dependencies]
-block = "0.1"
+block2 = "0.2.0"
 bitflags = "1.0"
 libc = "0.2"
 core-foundation = { path = "../core-foundation", version = "0.9" }
-core-graphics-types = { path = "../core-graphics-types", version = "0.1" }
-objc = "0.2.3"
+core-graphics-types = { path = "../core-graphics-types", version = "0.1", features = ["objc2"] }
+objc2 = "0.4.0"
diff --git a/cocoa-foundation/src/base.rs b/cocoa-foundation/src/base.rs
index 028205e89..ae0dbf923 100644
--- a/cocoa-foundation/src/base.rs
+++ b/cocoa-foundation/src/base.rs
@@ -7,9 +7,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use objc::runtime;
+use objc2::runtime;
 
-pub use objc::runtime::{BOOL, NO, YES};
+pub type BOOL = runtime::BOOL;
+pub const NO: BOOL = runtime::NO;
+pub const YES: BOOL = runtime::YES;
 
 pub type Class = *mut runtime::Class;
 #[allow(non_camel_case_types)]
diff --git a/cocoa-foundation/src/foundation.rs b/cocoa-foundation/src/foundation.rs
index 26da47e65..9760754e4 100644
--- a/cocoa-foundation/src/foundation.rs
+++ b/cocoa-foundation/src/foundation.rs
@@ -10,8 +10,9 @@
 #![allow(non_upper_case_globals)]
 
 use base::{id, nil, BOOL, NO, SEL};
-use block::Block;
+use block2::Block;
 use libc;
+use objc2::encode::{Encode, Encoding, RefEncode};
 use std::os::raw::c_void;
 use std::ptr;
 
@@ -35,7 +36,7 @@ mod macos {
     use base::id;
     use core_graphics_types::base::CGFloat;
     use core_graphics_types::geometry::CGRect;
-    use objc;
+    use objc2::encode::{Encode, Encoding};
     use std::mem;
 
     #[repr(C)]
@@ -52,15 +53,9 @@ mod macos {
         }
     }
 
-    unsafe impl objc::Encode for NSPoint {
-        fn encode() -> objc::Encoding {
-            let encoding = format!(
-                "{{CGPoint={}{}}}",
-                CGFloat::encode().as_str(),
-                CGFloat::encode().as_str()
-            );
-            unsafe { objc::Encoding::from_str(&encoding) }
-        }
+    unsafe impl Encode for NSPoint {
+        const ENCODING: Encoding =
+            Encoding::Struct("CGPoint", &[CGFloat::ENCODING, CGFloat::ENCODING]);
     }
 
     #[repr(C)]
@@ -80,15 +75,9 @@ mod macos {
         }
     }
 
-    unsafe impl objc::Encode for NSSize {
-        fn encode() -> objc::Encoding {
-            let encoding = format!(
-                "{{CGSize={}{}}}",
-                CGFloat::encode().as_str(),
-                CGFloat::encode().as_str()
-            );
-            unsafe { objc::Encoding::from_str(&encoding) }
-        }
+    unsafe impl Encode for NSSize {
+        const ENCODING: Encoding =
+            Encoding::Struct("CGSize", &[CGFloat::ENCODING, CGFloat::ENCODING]);
     }
 
     #[repr(C)]
@@ -118,15 +107,9 @@ mod macos {
         }
     }
 
-    unsafe impl objc::Encode for NSRect {
-        fn encode() -> objc::Encoding {
-            let encoding = format!(
-                "{{CGRect={}{}}}",
-                NSPoint::encode().as_str(),
-                NSSize::encode().as_str()
-            );
-            unsafe { objc::Encoding::from_str(&encoding) }
-        }
+    unsafe impl Encode for NSRect {
+        const ENCODING: Encoding =
+            Encoding::Struct("CGRect", &[NSPoint::ENCODING, NSSize::ENCODING]);
     }
 
     // Same as CGRectEdge
@@ -138,6 +121,8 @@ mod macos {
         NSRectMaxYEdge,
     }
 
+    impl_Encode!(NSRectEdge, u32);
+
     #[link(name = "Foundation", kind = "framework")]
     extern "C" {
         fn NSInsetRect(rect: NSRect, x: CGFloat, y: CGFloat) -> NSRect;
@@ -166,6 +151,11 @@ pub struct NSRange {
     pub length: NSUInteger,
 }
 
+unsafe impl Encode for NSRange {
+    const ENCODING: Encoding =
+        Encoding::Struct("_NSRange", &[NSUInteger::ENCODING, NSUInteger::ENCODING]);
+}
+
 impl NSRange {
     #[inline]
     pub fn new(location: NSUInteger, length: NSUInteger) -> NSRange {
@@ -208,6 +198,17 @@ pub struct NSOperatingSystemVersion {
     pub patchVersion: NSUInteger,
 }
 
+unsafe impl Encode for NSOperatingSystemVersion {
+    const ENCODING: Encoding = Encoding::Struct(
+        "NSOperatingSystemVersion",
+        &[
+            NSUInteger::ENCODING,
+            NSUInteger::ENCODING,
+            NSUInteger::ENCODING,
+        ],
+    );
+}
+
 impl NSOperatingSystemVersion {
     #[inline]
     pub fn new(
@@ -248,7 +249,8 @@ impl NSProcessInfo for id {
     }
 
     unsafe fn isOperatingSystemAtLeastVersion(self, version: NSOperatingSystemVersion) -> bool {
-        msg_send![self, isOperatingSystemAtLeastVersion: version]
+        let res: BOOL = msg_send![self, isOperatingSystemAtLeastVersion: version];
+        res != NO
     }
 }
 
@@ -628,6 +630,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSEnumerationOptions, libc::c_ulonglong);
+
 pub type NSComparator = *mut Block<(id, id), NSComparisonResult>;
 
 #[repr(isize)]
@@ -638,6 +642,8 @@ pub enum NSComparisonResult {
     NSOrderedDescending = 1,
 }
 
+impl_Encode!(NSComparisonResult, isize);
+
 pub trait NSString: Sized {
     unsafe fn alloc(_: Self) -> id {
         msg_send![class!(NSString), alloc]
@@ -664,9 +670,9 @@ impl NSString for id {
 
     unsafe fn init_str(self, string: &str) -> id {
         return msg_send![self,
-                         initWithBytes:string.as_ptr()
+                         initWithBytes:string.as_ptr() as *const c_void
                              length:string.len()
-                             encoding:UTF8_ENCODING as id];
+                             encoding:UTF8_ENCODING];
     }
 
     unsafe fn len(self) -> usize {
@@ -702,6 +708,22 @@ struct NSFastEnumerationState {
     pub extra: [libc::c_ulong; 5],
 }
 
+unsafe impl Encode for NSFastEnumerationState {
+    const ENCODING: Encoding = Encoding::Struct(
+        "?",
+        &[
+            libc::c_ulong::ENCODING,
+            Encoding::Pointer(&Encoding::Object),
+            Encoding::Pointer(&libc::c_ulong::ENCODING),
+            Encoding::Array(5, &libc::c_ulong::ENCODING),
+        ],
+    );
+}
+
+unsafe impl RefEncode for NSFastEnumerationState {
+    const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING);
+}
+
 const NS_FAST_ENUM_BUF_SIZE: usize = 16;
 
 pub struct NSFastIterator {
@@ -810,6 +832,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSURLBookmarkCreationOptions, NSUInteger);
+
 pub type NSURLBookmarkFileCreationOptions = NSURLBookmarkCreationOptions;
 
 bitflags! {
@@ -820,6 +844,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSURLBookmarkResolutionOptions, NSUInteger);
+
 pub trait NSURL: Sized {
     unsafe fn alloc(_: Self) -> id;
 
@@ -1606,6 +1632,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSDataReadingOptions, libc::c_ulonglong);
+
 bitflags! {
     pub struct NSDataBase64EncodingOptions: libc::c_ulonglong {
         const NSDataBase64Encoding64CharacterLineLength = 1 << 0;
@@ -1615,12 +1643,16 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSDataBase64EncodingOptions, libc::c_ulonglong);
+
 bitflags! {
     pub struct NSDataBase64DecodingOptions: libc::c_ulonglong {
        const NSDataBase64DecodingIgnoreUnknownCharacters = 1 << 0;
     }
 }
 
+impl_Encode!(NSDataBase64DecodingOptions, libc::c_ulonglong);
+
 bitflags! {
     pub struct NSDataWritingOptions: libc::c_ulonglong {
         const NSDataWritingAtomic = 1 << 0;
@@ -1628,6 +1660,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSDataWritingOptions, libc::c_ulonglong);
+
 bitflags! {
     pub struct NSDataSearchOptions: libc::c_ulonglong {
         const NSDataSearchBackwards = 1 << 0;
@@ -1635,6 +1669,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSDataSearchOptions, libc::c_ulonglong);
+
 pub trait NSUserDefaults {
     unsafe fn standardUserDefaults() -> Self;
 
diff --git a/cocoa-foundation/src/lib.rs b/cocoa-foundation/src/lib.rs
index 7cd0350f6..dcce624e3 100644
--- a/cocoa-foundation/src/lib.rs
+++ b/cocoa-foundation/src/lib.rs
@@ -8,15 +8,25 @@
 // except according to those terms.
 
 #![allow(non_snake_case)]
+#![allow(deprecated)] // TODO(madsmtm): Remove this
 
-extern crate block;
+extern crate block2;
 #[macro_use]
 extern crate bitflags;
 extern crate core_foundation;
 extern crate core_graphics_types;
 extern crate libc;
 #[macro_use]
-extern crate objc;
+pub extern crate objc2;
+
+#[macro_export]
+macro_rules! impl_Encode {
+    ($t:ty, $delegation:ty) => {
+        unsafe impl $crate::objc2::encode::Encode for $t {
+            const ENCODING: $crate::objc2::encode::Encoding = <$delegation>::ENCODING;
+        }
+    };
+}
 
 pub mod base;
 pub mod foundation;
diff --git a/cocoa-foundation/tests/foundation.rs b/cocoa-foundation/tests/foundation.rs
index 19d7b15c4..9051320d8 100644
--- a/cocoa-foundation/tests/foundation.rs
+++ b/cocoa-foundation/tests/foundation.rs
@@ -1,6 +1,6 @@
 #[macro_use]
-extern crate objc;
-extern crate block;
+extern crate objc2;
+extern crate block2;
 extern crate cocoa_foundation;
 
 #[cfg(test)]
@@ -108,7 +108,7 @@ mod foundation {
     }
 
     mod nsdictionary {
-        use block::ConcreteBlock;
+        use block2::ConcreteBlock;
         use cocoa_foundation::base::{id, nil};
         use cocoa_foundation::foundation::{
             NSArray, NSComparisonResult, NSDictionary, NSFastEnumeration, NSString,
@@ -164,16 +164,18 @@ mod foundation {
                 }
 
                 // First test cocoa sorting...
-                let mut comparator =
+                let comparator =
                     ConcreteBlock::new(|s0: id, s1: id| match compare_function(&s0, &s1) {
                         Ordering::Less => NSComparisonResult::NSOrderedAscending,
                         Ordering::Equal => NSComparisonResult::NSOrderedSame,
                         Ordering::Greater => NSComparisonResult::NSOrderedDescending,
                     });
+                let comparator_ptr: *const _ = &*comparator;
+                let comparator_ptr = comparator_ptr as *mut _;
 
                 let associated_iter = keys.iter().zip(objects.iter());
                 for (k_id, (k, v)) in dict
-                    .keysSortedByValueUsingComparator_(&mut *comparator)
+                    .keysSortedByValueUsingComparator_(comparator_ptr)
                     .iter()
                     .zip(associated_iter)
                 {
diff --git a/cocoa/Cargo.toml b/cocoa/Cargo.toml
index 96b0f424e..eae77b572 100644
--- a/cocoa/Cargo.toml
+++ b/cocoa/Cargo.toml
@@ -12,11 +12,11 @@ license = "MIT OR Apache-2.0"
 default-target = "x86_64-apple-darwin"
 
 [dependencies]
-block = "0.1"
+block2 = "0.2.0"
 bitflags = "1.0"
 libc = "0.2"
 cocoa-foundation = { path = "../cocoa-foundation", version = "0.1" }
 core-foundation = { path = "../core-foundation", version = "0.9" }
 core-graphics = { path = "../core-graphics", version = "0.23" }
 foreign-types = "0.5"
-objc = "0.2.3"
+objc2 = "0.4.0"
diff --git a/cocoa/examples/fullscreen.rs b/cocoa/examples/fullscreen.rs
index e3772e47b..fb80802b8 100644
--- a/cocoa/examples/fullscreen.rs
+++ b/cocoa/examples/fullscreen.rs
@@ -1,8 +1,6 @@
 extern crate cocoa;
 extern crate core_graphics;
-
-#[macro_use]
-extern crate objc;
+extern crate objc2;
 
 use cocoa::appkit::{
     NSApp, NSApplication, NSApplicationActivateIgnoringOtherApps,
@@ -17,8 +15,9 @@ use cocoa::foundation::{
 
 use core_graphics::display::CGDisplay;
 
-use objc::declare::ClassDecl;
-use objc::runtime::{Object, Sel};
+use objc2::declare::ClassBuilder;
+use objc2::runtime::{Object, Sel};
+use objc2::{class, msg_send, sel};
 
 fn main() {
     unsafe {
@@ -48,7 +47,7 @@ fn main() {
 
         // Create NSWindowDelegate
         let superclass = class!(NSObject);
-        let mut decl = ClassDecl::new("MyWindowDelegate", superclass).unwrap();
+        let mut decl = ClassBuilder::new("MyWindowDelegate", superclass).unwrap();
 
         extern "C" fn will_use_fillscreen_presentation_options(
             _: &Object,
@@ -75,16 +74,15 @@ fn main() {
 
         decl.add_method(
             sel!(window:willUseFullScreenPresentationOptions:),
-            will_use_fillscreen_presentation_options
-                as extern "C" fn(&Object, Sel, id, NSUInteger) -> NSUInteger,
+            will_use_fillscreen_presentation_options as extern "C" fn(_, _, _, _) -> _,
         );
         decl.add_method(
             sel!(windowWillEnterFullScreen:),
-            window_entering_fullscreen as extern "C" fn(&Object, Sel, id),
+            window_entering_fullscreen as extern "C" fn(_, _, _),
         );
         decl.add_method(
             sel!(windowDidEnterFullScreen:),
-            window_entering_fullscreen as extern "C" fn(&Object, Sel, id),
+            window_entering_fullscreen as extern "C" fn(_, _, _),
         );
 
         let delegate_class = decl.register();
diff --git a/cocoa/examples/nsvisualeffectview_blur.rs b/cocoa/examples/nsvisualeffectview_blur.rs
index b3fb07cdd..8918a9548 100644
--- a/cocoa/examples/nsvisualeffectview_blur.rs
+++ b/cocoa/examples/nsvisualeffectview_blur.rs
@@ -1,8 +1,8 @@
 extern crate cocoa;
-extern crate objc;
+extern crate objc2;
 
 use cocoa::base::{nil, selector, NO};
-use objc::*;
+use objc2::msg_send;
 
 use cocoa::appkit::{
     NSApp, NSApplication, NSApplicationActivationPolicyRegular, NSBackingStoreType, NSColor,
@@ -73,7 +73,7 @@ fn main() {
         blurred_view.setState_(NSVisualEffectState::FollowsWindowActiveState);
         blurred_view.setAutoresizingMask_(NSViewWidthSizable | NSViewHeightSizable);
 
-        let _: () = msg_send![ns_view, addSubview: blurred_view positioned: NSWindowOrderingMode::NSWindowBelow relativeTo: 0];
+        let _: () = msg_send![ns_view, addSubview: blurred_view positioned: NSWindowOrderingMode::NSWindowBelow relativeTo: nil];
 
         app.run();
     }
diff --git a/cocoa/src/appkit.rs b/cocoa/src/appkit.rs
index c73839f95..60257728c 100644
--- a/cocoa/src/appkit.rs
+++ b/cocoa/src/appkit.rs
@@ -10,10 +10,11 @@
 #![allow(non_upper_case_globals)]
 
 use base::{id, BOOL, SEL};
-use block::Block;
+use block2::Block;
 use foundation::{
     NSInteger, NSPoint, NSRange, NSRect, NSRectEdge, NSSize, NSTimeInterval, NSUInteger,
 };
+use objc2::encode::{Encode, Encoding};
 use libc;
 
 pub use core_graphics::base::CGFloat;
@@ -168,6 +169,8 @@ pub enum NSApplicationActivationPolicy {
     NSApplicationActivationPolicyERROR = -1,
 }
 
+impl_Encode!(NSApplicationActivationPolicy, i64);
+
 #[repr(u64)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSApplicationActivationOptions {
@@ -175,6 +178,8 @@ pub enum NSApplicationActivationOptions {
     NSApplicationActivateIgnoringOtherApps = 1 << 1,
 }
 
+impl_Encode!(NSApplicationActivationOptions, u64);
+
 #[repr(u64)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSApplicationTerminateReply {
@@ -183,6 +188,8 @@ pub enum NSApplicationTerminateReply {
     NSTerminateLater = 2,
 }
 
+impl_Encode!(NSApplicationTerminateReply, u64);
+
 bitflags! {
     pub struct NSApplicationPresentationOptions : NSUInteger {
         const NSApplicationPresentationDefault = 0;
@@ -201,6 +208,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSApplicationPresentationOptions, NSUInteger);
+
 bitflags! {
     pub struct NSWindowStyleMask: NSUInteger {
         const NSBorderlessWindowMask      = 0;
@@ -219,6 +228,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSWindowStyleMask, NSUInteger);
+
 #[repr(u64)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSWindowTitleVisibility {
@@ -226,6 +237,8 @@ pub enum NSWindowTitleVisibility {
     NSWindowTitleHidden = 1,
 }
 
+impl_Encode!(NSWindowTitleVisibility, u64);
+
 #[repr(i64)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSWindowTabbingMode {
@@ -234,6 +247,8 @@ pub enum NSWindowTabbingMode {
     NSWindowTabbingModePreferred = 2,
 }
 
+impl_Encode!(NSWindowTabbingMode, i64);
+
 #[repr(u64)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSBackingStoreType {
@@ -242,6 +257,9 @@ pub enum NSBackingStoreType {
     NSBackingStoreBuffered = 2,
 }
 
+impl_Encode!(NSBackingStoreType, u64);
+
+#[repr(isize)]
 pub enum NSWindowToolbarStyle {
     NSWindowToolbarStyleAutomatic = 0,
     NSWindowToolbarStyleExpanded = 1,
@@ -250,6 +268,8 @@ pub enum NSWindowToolbarStyle {
     NSWindowToolbarStyleUnifiedCompact = 4,
 }
 
+impl_Encode!(NSWindowToolbarStyle, NSInteger);
+
 bitflags! {
     pub struct NSWindowOrderingMode: NSInteger {
         const NSWindowAbove =  1;
@@ -258,6 +278,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSWindowOrderingMode, NSInteger);
+
 bitflags! {
     pub struct NSAlignmentOptions: libc::c_ulonglong {
         const NSAlignMinXInward         = 1 << 0;
@@ -294,6 +316,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSAlignmentOptions, libc::c_ulonglong);
+
 #[repr(u64)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSOpenGLPixelFormatAttribute {
@@ -338,6 +362,8 @@ pub enum NSOpenGLPixelFormatAttribute {
     NSOpenGLPFAVirtualScreenCount = 128,
 }
 
+impl_Encode!(NSOpenGLPixelFormatAttribute, u64);
+
 #[repr(u64)]
 #[allow(non_camel_case_types)]
 #[derive(Clone, Copy, Debug, PartialEq)]
@@ -347,6 +373,8 @@ pub enum NSOpenGLPFAOpenGLProfiles {
     NSOpenGLProfileVersion4_1Core = 0x4100,
 }
 
+impl_Encode!(NSOpenGLPFAOpenGLProfiles, u64);
+
 #[repr(u64)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSOpenGLContextParameter {
@@ -362,6 +390,8 @@ pub enum NSOpenGLContextParameter {
     NSOpenGLCPMPSwapsInFlight = 315,
 }
 
+impl_Encode!(NSOpenGLContextParameter, u64);
+
 #[repr(u64)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSWindowButton {
@@ -374,6 +404,8 @@ pub enum NSWindowButton {
     NSWindowFullScreenButton = 7,
 }
 
+impl_Encode!(NSWindowButton, u64);
+
 #[repr(u64)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSBezelStyle {
@@ -391,18 +423,22 @@ pub enum NSBezelStyle {
     NSRoundedDisclosureBezelStyle = 14,
 }
 
+impl_Encode!(NSBezelStyle, u64);
+
 // https://developer.apple.com/documentation/appkit/nsvisualeffectview/blendingmode
 #[allow(dead_code)]
-#[repr(u64)]
+#[repr(isize)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSVisualEffectBlendingMode {
     BehindWindow = 0,
     WithinWindow = 1,
 }
 
+impl_Encode!(NSVisualEffectBlendingMode, isize);
+
 // https://developer.apple.com/documentation/appkit/nsvisualeffectview/state
 #[allow(dead_code)]
-#[repr(u64)]
+#[repr(isize)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSVisualEffectState {
     FollowsWindowActiveState = 0,
@@ -410,8 +446,10 @@ pub enum NSVisualEffectState {
     Inactive = 2,
 }
 
+impl_Encode!(NSVisualEffectState, isize);
+
 /// <https://developer.apple.com/documentation/appkit/nsvisualeffectview/material>
-#[repr(u64)]
+#[repr(isize)]
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum NSVisualEffectMaterial {
     /// A default material for the view's effectiveAppearance.
@@ -447,6 +485,8 @@ pub enum NSVisualEffectMaterial {
     UnderPageBackground = 22,
 }
 
+impl_Encode!(NSVisualEffectMaterial, isize);
+
 // macOS 10.10+ - https://developer.apple.com/documentation/appkit/nsvisualeffectview
 #[allow(non_snake_case)]
 pub trait NSVisualEffectView: Sized {
@@ -537,6 +577,8 @@ pub enum NSRequestUserAttentionType {
     NSInformationalRequest = 10,
 }
 
+impl_Encode!(NSRequestUserAttentionType, u64);
+
 pub static NSMainMenuWindowLevel: i32 = 24;
 
 pub trait NSApplication: Sized {
@@ -546,7 +588,7 @@ pub trait NSApplication: Sized {
 
     unsafe fn mainMenu(self) -> id;
     unsafe fn setActivationPolicy_(self, policy: NSApplicationActivationPolicy) -> BOOL;
-    unsafe fn setPresentationOptions_(self, options: NSApplicationPresentationOptions) -> BOOL;
+    unsafe fn setPresentationOptions_(self, options: NSApplicationPresentationOptions);
     unsafe fn presentationOptions_(self) -> NSApplicationPresentationOptions;
     unsafe fn setMainMenu_(self, menu: id);
     unsafe fn setServicesMenu_(self, menu: id);
@@ -577,7 +619,7 @@ impl NSApplication for id {
         msg_send![self, setActivationPolicy: policy as NSInteger]
     }
 
-    unsafe fn setPresentationOptions_(self, options: NSApplicationPresentationOptions) -> BOOL {
+    unsafe fn setPresentationOptions_(self, options: NSApplicationPresentationOptions) {
         msg_send![self, setPresentationOptions:options.bits]
     }
 
@@ -956,12 +998,16 @@ pub enum NSPasteboardReadingOptions {
     NSPasteboardReadingAsKeyedArchive = 1 << 2,
 }
 
+impl_Encode!(NSPasteboardReadingOptions, u64);
+
 #[repr(u64)]
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum NSPasteboardWritingOptions {
     NSPasteboardWritingPromised = 1 << 9,
 }
 
+impl_Encode!(NSPasteboardWritingOptions, u64);
+
 pub trait NSMenu: Sized {
     unsafe fn alloc(_: Self) -> id {
         msg_send![class!(NSMenu), alloc]
@@ -1058,12 +1104,16 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSWindowCollectionBehavior, NSUInteger);
+
 bitflags! {
     pub struct NSWindowOcclusionState: NSUInteger {
         const NSWindowOcclusionStateVisible = 1 << 1;
     }
 }
 
+impl_Encode!(NSWindowOcclusionState, NSUInteger);
+
 pub trait NSWindow: Sized {
     unsafe fn alloc(_: Self) -> id {
         msg_send![class!(NSWindow), alloc]
@@ -2108,6 +2158,8 @@ pub enum NSModalResponse {
     NSModalResponseCancel = 0,
 }
 
+impl_Encode!(NSModalResponse, i64);
+
 pub trait NSSavePanel: Sized {
     unsafe fn savePanel(_: Self) -> id {
         msg_send![class!(NSSavePanel), savePanel]
@@ -2188,6 +2240,8 @@ pub enum NSViewLayerContentsPlacement {
     NSViewLayerContentsPlacementTopLeft = 11,
 }
 
+impl_Encode!(NSViewLayerContentsPlacement, usize);
+
 pub trait NSView: Sized {
     unsafe fn alloc(_: Self) -> id {
         msg_send![class!(NSView), alloc]
@@ -2378,7 +2432,7 @@ impl NSOpenGLPixelFormat for id {
     // Creating an NSOpenGLPixelFormat Object
 
     unsafe fn initWithAttributes_(self, attributes: &[u32]) -> id {
-        msg_send![self, initWithAttributes: attributes]
+        msg_send![self, initWithAttributes:attributes.as_ptr()]
     }
 
     // Managing the Pixel Format
@@ -2523,6 +2577,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSEventSwipeTrackingOptions, NSUInteger);
+
 #[repr(i64)] // NSInteger
 pub enum NSEventGestureAxis {
     NSEventGestureAxisNone = 0,
@@ -2530,6 +2586,8 @@ pub enum NSEventGestureAxis {
     NSEventGestureAxisVertical,
 }
 
+impl_Encode!(NSEventGestureAxis, i64);
+
 bitflags! {
     pub struct NSEventPhase: NSUInteger {
        const NSEventPhaseNone        = 0;
@@ -2542,6 +2600,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSEventPhase, NSUInteger);
+
 bitflags! {
     pub struct NSTouchPhase: NSUInteger {
         const NSTouchPhaseBegan         = 1 << 0;
@@ -2556,6 +2616,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSTouchPhase, NSUInteger);
+
 #[derive(Clone, Copy, Debug, PartialEq)]
 #[repr(u64)] // NSUInteger
 pub enum NSEventType {
@@ -2591,6 +2653,8 @@ pub enum NSEventType {
     NSEventTypePressure = 34,
 }
 
+impl_Encode!(NSEventType, u64);
+
 bitflags! {
     pub struct NSEventMask: libc::c_ulonglong {
         const NSLeftMouseDownMask         = 1 << NSLeftMouseDown as libc::c_ulonglong;
@@ -2626,6 +2690,8 @@ bitflags! {
     }
 }
 
+impl_Encode!(NSEventMask, libc::c_ulonglong);
+
 impl NSEventMask {
     pub fn from_type(ty: NSEventType) -> NSEventMask {
         NSEventMask {
@@ -2648,8 +2714,11 @@ bitflags! {
     }
 }
 
-// Not sure of the type here
+impl_Encode!(NSEventModifierFlags, NSUInteger);
+
+#[repr(usize)] // NSUInteger
 pub enum NSPointingDeviceType {
+    __Unknown = 0,
     // TODO: Not sure what these values are
     // NSUnknownPointingDevice = NX_TABLET_POINTER_UNKNOWN,
     // NSPenPointingDevice     = NX_TABLET_POINTER_PEN,
@@ -2657,14 +2726,19 @@ pub enum NSPointingDeviceType {
     // NSEraserPointingDevice  = NX_TABLET_POINTER_ERASER,
 }
 
-// Not sure of the type here
+impl_Encode!(NSPointingDeviceType, usize);
+
+#[repr(usize)] // NSUInteger
 pub enum NSEventButtonMask {
+    __Unknown = 0,
     // TODO: Not sure what these values are
     // NSPenTipMask =       NX_TABLET_BUTTON_PENTIPMASK,
     // NSPenLowerSideMask = NX_TABLET_BUTTON_PENLOWERSIDEMASK,
     // NSPenUpperSideMask = NX_TABLET_BUTTON_PENUPPERSIDEMASK,
 }
 
+impl_Encode!(NSEventButtonMask, usize);
+
 #[repr(i16)]
 pub enum NSEventSubtype {
     // TODO: Not sure what these values are
@@ -2680,6 +2754,8 @@ pub enum NSEventSubtype {
     NSAWTEventType = 16,
 }
 
+impl_Encode!(NSEventSubtype, i16);
+
 pub const NSUpArrowFunctionKey: libc::c_ushort = 0xF700;
 pub const NSDownArrowFunctionKey: libc::c_ushort = 0xF701;
 pub const NSLeftArrowFunctionKey: libc::c_ushort = 0xF702;
@@ -3461,7 +3537,7 @@ pub trait NSButton: Sized {
     }
     unsafe fn initWithFrame_(self, frameRect: NSRect) -> id;
     unsafe fn setTarget_(self, target: id /* Instance */);
-    unsafe fn setAction_(self, selector: objc::runtime::Sel /* (Instance *) */);
+    unsafe fn setAction_(self, selector: objc2::runtime::Sel /* (Instance *) */);
 }
 
 impl NSButton for id {
@@ -3481,7 +3557,7 @@ impl NSButton for id {
         msg_send![self, setTarget: target]
     }
 
-    unsafe fn setAction_(self, selector: objc::runtime::Sel /* (Instance method *) */) {
+    unsafe fn setAction_(self, selector: objc2::runtime::Sel /* (Instance method *) */) {
         msg_send![self, setAction: selector]
     }
 }
@@ -3929,6 +4005,8 @@ pub enum NSCompositingOperation {
     NSCompositePlusLighter = 13,
 }
 
+impl_Encode!(NSCompositingOperation, usize);
+
 #[repr(usize)]
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum NSImageCacheMode {
@@ -3938,6 +4016,8 @@ pub enum NSImageCacheMode {
     NSImageCacheNever,
 }
 
+impl_Encode!(NSImageCacheMode, usize);
+
 #[repr(usize)]
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum NSTIFFCompression {
@@ -3951,6 +4031,8 @@ pub enum NSTIFFCompression {
     NSTIFFCompressionOldJPEG = 32865,
 }
 
+impl_Encode!(NSTIFFCompression, usize);
+
 #[repr(usize)]
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub enum NSImageLoadStatus {
@@ -3961,6 +4043,8 @@ pub enum NSImageLoadStatus {
     NSImageLoadStatusReadError,
 }
 
+impl_Encode!(NSImageLoadStatus, usize);
+
 pub trait NSSound: Sized {
     unsafe fn canInitWithPasteboard_(_: Self, pasteboard: id) -> BOOL {
         msg_send![class!(NSSound), canInitWithPasteboard: pasteboard]
@@ -4165,6 +4249,8 @@ pub enum NSTabViewType {
     NSNoTabsNoBorder = 6,
 }
 
+impl_Encode!(NSTabViewType, u64);
+
 pub trait NSTabView: Sized {
     unsafe fn new(_: Self) -> id {
         msg_send![class!(NSTabView), new]
@@ -4343,6 +4429,8 @@ pub enum NSTabState {
     NSPressedTab = 2,
 }
 
+impl_Encode!(NSTabState, u64);
+
 pub trait NSTabViewItem: Sized {
     unsafe fn alloc(_: Self) -> id {
         msg_send![class!(NSTabViewItem), alloc]
@@ -4493,6 +4581,13 @@ pub trait NSColorSpace: Sized {
     unsafe fn localizedName(self) -> id;
 }
 
+#[repr(transparent)]
+struct CGColorSpaceRef(*const c_void);
+
+unsafe impl Encode for CGColorSpaceRef {
+    const ENCODING: Encoding = Encoding::Pointer(&Encoding::Struct("CGColorSpace", &[]));
+}
+
 impl NSColorSpace for id {
     unsafe fn deviceRGBColorSpace(_: Self) -> id {
         msg_send![class!(NSColorSpace), deviceRGBColorSpace]
@@ -4537,12 +4632,13 @@ impl NSColorSpace for id {
 
     unsafe fn initWithCGColorSpace_(
         self,
-        cg_color_space: *const c_void, /* (CGColorSpaceRef) */
+        cg_color_space: *const c_void,
     ) -> id {
-        msg_send![self, initWithCGColorSpace: cg_color_space]
+        msg_send![self, initWithCGColorSpace: CGColorSpaceRef(cg_color_space)]
     }
-    unsafe fn CGColorSpace(self) -> *const c_void /* (CGColorSpaceRef) */ {
-        msg_send![self, CGColorSpace]
+    unsafe fn CGColorSpace(self) -> *const c_void {
+        let res: CGColorSpaceRef = msg_send![self, CGColorSpace];
+        res.0
     }
     unsafe fn localizedName(self) -> id {
         msg_send![self, localizedName]
@@ -4941,7 +5037,7 @@ impl NSDockTile for id {
 }
 
 pub unsafe fn NSAppearance(named: id /* NSAppearanceName */) -> id {
-    objc::msg_send![class!(NSAppearance), appearanceNamed: named]
+    msg_send![class!(NSAppearance), appearanceNamed: named]
 }
 
 #[cfg(test)]
diff --git a/cocoa/src/lib.rs b/cocoa/src/lib.rs
index 0d75b7622..eca26e773 100644
--- a/cocoa/src/lib.rs
+++ b/cocoa/src/lib.rs
@@ -10,17 +10,19 @@
 #![crate_name = "cocoa"]
 #![crate_type = "rlib"]
 #![allow(non_snake_case)]
+#![allow(deprecated)] // TODO(madsmtm): Remove this
 
-extern crate block;
+extern crate block2;
 #[macro_use]
 extern crate bitflags;
+#[macro_use]
 extern crate cocoa_foundation;
 extern crate core_foundation;
 extern crate core_graphics;
 extern crate foreign_types;
 extern crate libc;
 #[macro_use]
-extern crate objc;
+extern crate objc2;
 
 #[cfg(target_os = "macos")]
 pub mod appkit;
diff --git a/cocoa/src/macros.rs b/cocoa/src/macros.rs
index 77c6a16d3..d6d0b5f97 100644
--- a/cocoa/src/macros.rs
+++ b/cocoa/src/macros.rs
@@ -13,12 +13,12 @@
 /// # Example with NSWindowDelegate
 /// ``` no_run
 /// #[macro_use] extern crate cocoa;
-/// #[macro_use] extern crate objc;
+/// #[macro_use] extern crate objc2;
 ///
 /// use cocoa::appkit::NSWindow;
 /// use cocoa::base::{id, nil};
 ///
-/// use objc::runtime::{Object, Sel};
+/// use objc2::runtime::{Object, Sel};
 ///
 /// # fn main() {
 /// unsafe {
@@ -33,7 +33,7 @@
 ///
 ///     my_window.setDelegate_(delegate!("MyWindowDelegate", {
 ///         window: id = my_window, // Declare instance variable(s)
-///         (onWindowWillEnterFullscreen:) => on_enter_fullscreen as extern fn(&Object, Sel, id) // Declare function(s)
+///         (onWindowWillEnterFullscreen:) => on_enter_fullscreen as extern fn(_, _, _) // Declare function(s)
 ///     }));
 /// }
 /// # }
@@ -57,7 +57,7 @@ macro_rules! delegate {
             $( ($($sel:ident :)+) => $func:expr),*
         }
     ) => ({
-        let mut decl = objc::declare::ClassDecl::new($name, class!(NSObject)).unwrap();
+        let mut decl = objc2::declare::ClassDecl::new($name, class!(NSObject)).unwrap();
 
         $(
             decl.add_ivar::<$var_type>(stringify!($var));
diff --git a/cocoa/src/quartzcore.rs b/cocoa/src/quartzcore.rs
index 5f4c6da28..f14b65be4 100644
--- a/cocoa/src/quartzcore.rs
+++ b/cocoa/src/quartzcore.rs
@@ -21,6 +21,7 @@ use core_graphics::context::CGContext;
 use core_graphics::geometry::{CGAffineTransform, CGPoint, CGRect, CGSize};
 use core_graphics::path::{CGPath, SysCGPathRef};
 use foreign_types::ForeignType;
+use objc2::encode::{Encode, Encoding, RefEncode};
 use std::ops::Mul;
 use std::ptr;
 
@@ -28,6 +29,38 @@ use appkit::CGLContextObj;
 use base::{id, nil, BOOL, YES};
 use foundation::NSUInteger;
 
+// Helper utilities for non-Encode types
+
+trait AsId {
+    fn as_id(&self) -> id;
+}
+
+impl<T: ?Sized + TCFType> AsId for T {
+    fn as_id(&self) -> id {
+        self.as_CFTypeRef() as *mut _
+    }
+}
+
+fn array_ref(obj: id) -> CFArrayRef {
+    obj.cast()
+}
+
+fn dictionary_ref(obj: id) -> CFDictionaryRef {
+    obj.cast()
+}
+
+fn string_ref(obj: id) -> CFStringRef {
+    obj.cast()
+}
+
+fn color_ref(obj: id) -> SysCGColorRef {
+    obj.cast()
+}
+
+fn path_ref(obj: id) -> SysCGPathRef {
+    obj.cast()
+}
+
 // CABase.h
 
 pub fn current_media_time() -> CFTimeInterval {
@@ -38,6 +71,8 @@ pub fn current_media_time() -> CFTimeInterval {
 
 pub struct CALayer(id);
 
+impl_Encode!(CALayer, id);
+
 unsafe impl Send for CALayer {}
 unsafe impl Sync for CALayer {}
 
@@ -86,13 +121,13 @@ impl CALayer {
 
     #[inline]
     pub fn default_value_for_key(key: &CFString) -> id {
-        unsafe { msg_send![class!(CALayer), defaultValueForKey:(key.as_CFTypeRef())] }
+        unsafe { msg_send![class!(CALayer), defaultValueForKey: key.as_id()] }
     }
 
     #[inline]
     pub fn needs_display_for_key(key: &CFString) -> bool {
         unsafe {
-            let flag: BOOL = msg_send![class!(CALayer), needsDisplayForKey:(key.as_CFTypeRef())];
+            let flag: BOOL = msg_send![class!(CALayer), needsDisplayForKey: key.as_id()];
             flag == YES
         }
     }
@@ -100,8 +135,7 @@ impl CALayer {
     #[inline]
     pub fn should_archive_value_for_key(key: &CFString) -> bool {
         unsafe {
-            let flag: BOOL =
-                msg_send![class!(CALayer), shouldArchiveValueForKey:(key.as_CFTypeRef())];
+            let flag: BOOL = msg_send![class!(CALayer), shouldArchiveValueForKey: key.as_id()];
             flag == YES
         }
     }
@@ -253,7 +287,7 @@ impl CALayer {
     #[inline]
     pub fn sublayers(&self) -> CFArray<CALayer> {
         unsafe {
-            let sublayers: CFArrayRef = msg_send![self.id(), sublayers];
+            let sublayers = array_ref(msg_send![self.id(), sublayers]);
             TCFType::wrap_under_create_rule(sublayers)
         }
     }
@@ -445,7 +479,7 @@ impl CALayer {
     #[inline]
     pub fn contents_gravity(&self) -> ContentsGravity {
         unsafe {
-            let string: CFStringRef = msg_send![self.id(), contentsGravity];
+            let string = string_ref(msg_send![self.id(), contentsGravity]);
             ContentsGravity::from_CFString(TCFType::wrap_under_create_rule(string))
         }
     }
@@ -454,7 +488,7 @@ impl CALayer {
     pub fn set_contents_gravity(&self, new_contents_gravity: ContentsGravity) {
         unsafe {
             let contents_gravity: CFString = new_contents_gravity.into_CFString();
-            msg_send![self.id(), setContentsGravity:contents_gravity.as_CFTypeRef()]
+            msg_send![self.id(), setContentsGravity: contents_gravity.as_id()]
         }
     }
 
@@ -481,7 +515,7 @@ impl CALayer {
     #[inline]
     pub fn contents_format(&self) -> ContentsFormat {
         unsafe {
-            let string: CFStringRef = msg_send![self.id(), contentsFormat];
+            let string = string_ref(msg_send![self.id(), contentsFormat]);
             ContentsFormat::from_CFString(TCFType::wrap_under_create_rule(string))
         }
     }
@@ -490,14 +524,14 @@ impl CALayer {
     pub fn set_contents_format(&self, new_contents_format: ContentsFormat) {
         unsafe {
             let contents_format: CFString = new_contents_format.into_CFString();
-            msg_send![self.id(), setContentsFormat:contents_format.as_CFTypeRef()]
+            msg_send![self.id(), setContentsFormat: contents_format.as_id()]
         }
     }
 
     #[inline]
     pub fn minification_filter(&self) -> Filter {
         unsafe {
-            let string: CFStringRef = msg_send![self.id(), minificationFilter];
+            let string = string_ref(msg_send![self.id(), minificationFilter]);
             Filter::from_CFString(TCFType::wrap_under_create_rule(string))
         }
     }
@@ -506,14 +540,14 @@ impl CALayer {
     pub fn set_minification_filter(&self, new_filter: Filter) {
         unsafe {
             let filter: CFString = new_filter.into_CFString();
-            msg_send![self.id(), setMinificationFilter:filter.as_CFTypeRef()]
+            msg_send![self.id(), setMinificationFilter: filter.as_id()]
         }
     }
 
     #[inline]
     pub fn magnification_filter(&self) -> Filter {
         unsafe {
-            let string: CFStringRef = msg_send![self.id(), magnificationFilter];
+            let string = string_ref(msg_send![self.id(), magnificationFilter]);
             Filter::from_CFString(TCFType::wrap_under_create_rule(string))
         }
     }
@@ -522,7 +556,7 @@ impl CALayer {
     pub fn set_magnification_filter(&self, new_filter: Filter) {
         unsafe {
             let filter: CFString = new_filter.into_CFString();
-            msg_send![self.id(), setMagnificationFilter:filter.as_CFTypeRef()]
+            msg_send![self.id(), setMagnificationFilter: filter.as_id()]
         }
     }
 
@@ -605,12 +639,14 @@ impl CALayer {
 
     #[inline]
     pub fn draw_in_context(&self, context: &CGContext) {
-        unsafe { msg_send![self.id(), drawInContext:(*context).as_ptr()] }
+        let context: id = (*context).as_ptr().cast();
+        unsafe { msg_send![self.id(), drawInContext: context] }
     }
 
     #[inline]
     pub fn render_in_context(&self, context: &CGContext) {
-        unsafe { msg_send![self.id(), renderInContext:(*context).as_ptr()] }
+        let context: id = (*context).as_ptr().cast();
+        unsafe { msg_send![self.id(), renderInContext: context] }
     }
 
     #[inline]
@@ -628,7 +664,7 @@ impl CALayer {
     #[inline]
     pub fn background_color(&self) -> Option<CGColor> {
         unsafe {
-            let color: SysCGColorRef = msg_send![self.id(), backgroundColor];
+            let color = color_ref(msg_send![self.id(), backgroundColor]);
             if color.is_null() {
                 None
             } else {
@@ -641,8 +677,8 @@ impl CALayer {
     pub fn set_background_color(&self, color: Option<CGColor>) {
         unsafe {
             let color = match color {
-                None => ptr::null(),
-                Some(color) => color.as_CFTypeRef(),
+                None => ptr::null_mut(),
+                Some(color) => color.as_id(),
             };
             msg_send![self.id(), setBackgroundColor: color]
         }
@@ -681,7 +717,7 @@ impl CALayer {
     #[inline]
     pub fn border_color(&self) -> Option<CGColor> {
         unsafe {
-            let color: SysCGColorRef = msg_send![self.id(), borderColor];
+            let color = color_ref(msg_send![self.id(), borderColor]);
             if color.is_null() {
                 None
             } else {
@@ -694,8 +730,8 @@ impl CALayer {
     pub fn set_border_color(&self, color: Option<CGColor>) {
         unsafe {
             let color = match color {
-                None => ptr::null(),
-                Some(color) => color.as_CFTypeRef(),
+                None => ptr::null_mut(),
+                Some(color) => color.as_id(),
             };
             msg_send![self.id(), setBorderColor: color]
         }
@@ -723,7 +759,7 @@ impl CALayer {
 
     #[inline]
     pub unsafe fn filters(&self) -> Option<CFArray> {
-        let filters: CFArrayRef = msg_send![self.id(), filters];
+        let filters = array_ref(msg_send![self.id(), filters]);
         if filters.is_null() {
             None
         } else {
@@ -733,16 +769,16 @@ impl CALayer {
 
     #[inline]
     pub unsafe fn set_filters(&self, filters: Option<CFArray>) {
-        let filters: CFTypeRef = match filters {
-            Some(ref filters) => filters.as_CFTypeRef(),
-            None => ptr::null(),
+        let filters = match filters {
+            Some(ref filters) => filters.as_id(),
+            None => ptr::null_mut(),
         };
         msg_send![self.id(), setFilters: filters]
     }
 
     #[inline]
     pub unsafe fn background_filters(&self) -> Option<CFArray> {
-        let filters: CFArrayRef = msg_send![self.id(), backgroundFilters];
+        let filters = array_ref(msg_send![self.id(), backgroundFilters]);
         if filters.is_null() {
             None
         } else {
@@ -752,9 +788,9 @@ impl CALayer {
 
     #[inline]
     pub unsafe fn set_background_filters(&self, filters: Option<CFArray>) {
-        let filters: CFTypeRef = match filters {
-            Some(ref filters) => filters.as_CFTypeRef(),
-            None => ptr::null(),
+        let filters = match filters {
+            Some(ref filters) => filters.as_id(),
+            None => ptr::null_mut(),
         };
         msg_send![self.id(), setBackgroundFilters: filters]
     }
@@ -787,7 +823,7 @@ impl CALayer {
     #[inline]
     pub fn shadow_color(&self) -> Option<CGColor> {
         unsafe {
-            let color: SysCGColorRef = msg_send![self.id(), shadowColor];
+            let color = color_ref(msg_send![self.id(), shadowColor]);
             if color.is_null() {
                 None
             } else {
@@ -800,8 +836,8 @@ impl CALayer {
     pub fn set_shadow_color(&self, color: Option<CGColor>) {
         unsafe {
             let color = match color {
-                None => ptr::null(),
-                Some(color) => color.as_CFTypeRef(),
+                None => ptr::null_mut(),
+                Some(color) => color.as_id(),
             };
             msg_send![self.id(), setShadowColor: color]
         }
@@ -840,7 +876,7 @@ impl CALayer {
     #[inline]
     pub fn shadow_path(&self) -> Option<CGPath> {
         unsafe {
-            let path: SysCGPathRef = msg_send![self.id(), shadowPath];
+            let path = path_ref(msg_send![self.id(), shadowPath]);
             if path.is_null() {
                 None
             } else {
@@ -852,9 +888,9 @@ impl CALayer {
     #[inline]
     pub fn set_shadow_path(&self, path: Option<CGPath>) {
         unsafe {
-            let sys_path_ref = match path {
-                None => ptr::null(),
-                Some(path) => path.as_ptr(),
+            let sys_path_ref: id = match path {
+                None => ptr::null_mut(),
+                Some(path) => path.as_ptr().cast(),
             };
             msg_send![self.id(), setShadowPath: sys_path_ref]
         }
@@ -926,7 +962,7 @@ impl CALayer {
     pub fn default_action_for_key(event: &str) -> id {
         unsafe {
             let event: CFString = CFString::from(event);
-            msg_send![class!(CALayer), defaultActionForKey:event.as_CFTypeRef()]
+            msg_send![class!(CALayer), defaultActionForKey: event.as_id()]
         }
     }
 
@@ -934,29 +970,29 @@ impl CALayer {
     pub fn action_for_key(&self, event: &str) -> id {
         unsafe {
             let event: CFString = CFString::from(event);
-            msg_send![self.id(), actionForKey:event.as_CFTypeRef()]
+            msg_send![self.id(), actionForKey: event.as_id()]
         }
     }
 
     #[inline]
     pub fn actions(&self) -> CFDictionary<CFStringRef, CFTypeRef> {
-        unsafe { msg_send![self.id(), actions] }
+        unsafe { CFDictionary::wrap_under_get_rule(dictionary_ref(msg_send![self.id(), actions])) }
     }
 
     #[inline]
     pub unsafe fn set_actions(&self, actions: CFDictionary<CFStringRef, CFTypeRef>) {
-        msg_send![self.id(), setActions: actions]
+        msg_send![self.id(), setActions: actions.as_id()]
     }
 
     // TODO(pcwalton): Wrap `CAAnimation`.
     #[inline]
     pub unsafe fn add_animation_for_key(&self, animation: id, for_key: Option<&str>) {
         let for_key: Option<CFString> = for_key.map(CFString::from);
-        let for_key: CFTypeRef = match for_key {
-            Some(ref for_key) => for_key.as_CFTypeRef(),
-            None => ptr::null(),
+        let for_key = match for_key {
+            Some(ref for_key) => for_key.as_id(),
+            None => ptr::null_mut(),
         };
-        msg_send![self.id(), addAnimation:animation forKey:for_key]
+        msg_send![self.id(), addAnimation: animation forKey: for_key]
     }
 
     #[inline]
@@ -968,14 +1004,14 @@ impl CALayer {
     pub fn remove_animation_for_key(&self, key: &str) {
         unsafe {
             let key = CFString::from(key);
-            msg_send![self.id(), removeAnimationForKey:key.as_CFTypeRef()]
+            msg_send![self.id(), removeAnimationForKey: key.as_id()]
         }
     }
 
     #[inline]
     pub fn animation_keys(&self) -> Vec<String> {
         unsafe {
-            let keys: CFArrayRef = msg_send![self.id(), animationKeys];
+            let keys = array_ref(msg_send![self.id(), animationKeys]);
             let keys: CFArray = TCFType::wrap_under_create_rule(keys);
             keys.into_iter()
                 .map(|string| CFString::wrap_under_get_rule(*string as CFStringRef).to_string())
@@ -987,7 +1023,7 @@ impl CALayer {
     pub fn animation_for_key(&self, key: &str) -> id {
         unsafe {
             let key = CFString::from(key);
-            msg_send![self.id(), animationForKey:key.as_CFTypeRef()]
+            msg_send![self.id(), animationForKey: key.as_id()]
         }
     }
 
@@ -996,7 +1032,7 @@ impl CALayer {
     #[inline]
     pub fn name(&self) -> String {
         unsafe {
-            let name: CFStringRef = msg_send![self.id(), name];
+            let name = string_ref(msg_send![self.id(), name]);
             CFString::wrap_under_get_rule(name).to_string()
         }
     }
@@ -1005,7 +1041,7 @@ impl CALayer {
     pub fn set_name(&self, name: &str) {
         unsafe {
             let name = CFString::from(name);
-            msg_send![self.id(), setName:name.as_CFTypeRef()]
+            msg_send![self.id(), setName: name.as_id()]
         }
     }
 
@@ -1022,7 +1058,7 @@ impl CALayer {
     #[inline]
     pub fn style(&self) -> Option<CFDictionary> {
         unsafe {
-            let dictionary: CFDictionaryRef = msg_send![self.id(), style];
+            let dictionary = dictionary_ref(msg_send![self.id(), style]);
             if dictionary.is_null() {
                 None
             } else {
@@ -1035,8 +1071,8 @@ impl CALayer {
     pub fn set_style(&self, dictionary: Option<CFDictionary>) {
         unsafe {
             let dictionary = match dictionary {
-                None => ptr::null(),
-                Some(ref dictionary) => dictionary.as_CFTypeRef(),
+                None => ptr::null_mut(),
+                Some(ref dictionary) => dictionary.as_id(),
             };
             msg_send![self.id(), setStyle: dictionary]
         }
@@ -1048,7 +1084,7 @@ impl CALayer {
     pub fn reload_value_for_key_path(&self, key: &str) {
         unsafe {
             let key = CFString::from(key);
-            msg_send![self.id(), reloadValueForKeyPath:key.as_CFTypeRef()]
+            msg_send![self.id(), reloadValueForKeyPath: key.as_id()]
         }
     }
 
@@ -1209,6 +1245,8 @@ bitflags! {
 
 pub struct CARenderer(id);
 
+impl_Encode!(CARenderer, id);
+
 unsafe impl Send for CARenderer {}
 unsafe impl Sync for CARenderer {}
 
@@ -1247,8 +1285,8 @@ impl CARenderer {
 
         let options: CFDictionary<CFString, CFType> = CFDictionary::from_CFType_pairs(&pairs);
 
-        let renderer: id = msg_send![class!(CARenderer), rendererWithCGLContext:context
-                                                         options:options.as_CFTypeRef()];
+        let renderer: id = msg_send![class!(CARenderer), rendererWithCGLContext: context
+                                                         options: options.as_id()];
         debug_assert!(renderer != nil);
         CARenderer(renderer)
     }
@@ -1272,8 +1310,8 @@ impl CARenderer {
 
         let options: CFDictionary<CFString, CFType> = CFDictionary::from_CFType_pairs(&pairs);
 
-        let renderer: id = msg_send![class!(CARenderer), rendererWithMTLTexture:metal_texture
-                                                         options:options.as_CFTypeRef()];
+        let renderer: id = msg_send![class!(CARenderer), rendererWithMTLTexture: metal_texture
+                                                         options: options.as_id()];
         debug_assert!(renderer != nil);
         CARenderer(renderer)
     }
@@ -1352,10 +1390,11 @@ impl CARenderer {
 // You can't actually construct any `CATransaction` objects, so that class is
 // really just a module.
 pub mod transaction {
-    use block::{Block, ConcreteBlock, IntoConcreteBlock, RcBlock};
+    use block2::{Block, ConcreteBlock, IntoConcreteBlock, RcBlock};
     use core_foundation::date::CFTimeInterval;
     use core_foundation::string::CFString;
 
+    use super::AsId;
     use base::{id, BOOL, YES};
 
     #[inline]
@@ -1432,7 +1471,7 @@ pub mod transaction {
     #[inline]
     pub fn set_completion_block<F>(block: ConcreteBlock<(), (), F>)
     where
-        F: 'static + IntoConcreteBlock<(), Ret = ()>,
+        F: 'static + IntoConcreteBlock<(), Output = ()>,
     {
         unsafe {
             let block = block.copy();
@@ -1444,7 +1483,7 @@ pub mod transaction {
     pub fn value_for_key(key: &str) -> id {
         unsafe {
             let key: CFString = CFString::from(key);
-            msg_send![class!(CATransaction), valueForKey: key]
+            msg_send![class!(CATransaction), valueForKey: key.as_id()]
         }
     }
 
@@ -1452,7 +1491,7 @@ pub mod transaction {
     pub fn set_value_for_key(value: id, key: &str) {
         unsafe {
             let key: CFString = CFString::from(key);
-            msg_send![class!(CATransaction), setValue:value forKey:key]
+            msg_send![class!(CATransaction), setValue: value forKey: key.as_id()]
         }
     }
 }
@@ -1480,6 +1519,10 @@ pub struct CATransform3D {
     pub m44: CGFloat,
 }
 
+unsafe impl Encode for CATransform3D {
+    const ENCODING: Encoding = Encoding::Array(16, &CGFloat::ENCODING);
+}
+
 impl PartialEq for CATransform3D {
     #[inline]
     fn eq(&self, other: &CATransform3D) -> bool {
@@ -1631,6 +1674,27 @@ pub struct CVTimeStamp {
     pub reserved: u64,
 }
 
+unsafe impl Encode for CVTimeStamp {
+    const ENCODING: Encoding = Encoding::Struct(
+        "CVTimeStamp",
+        &[
+            u32::ENCODING,
+            i32::ENCODING,
+            i64::ENCODING,
+            u64::ENCODING,
+            f64::ENCODING,
+            i64::ENCODING,
+            CVSMPTETime::ENCODING,
+            u64::ENCODING,
+            u64::ENCODING,
+        ],
+    );
+}
+
+unsafe impl RefEncode for CVTimeStamp {
+    const ENCODING_REF: Encoding = Encoding::Pointer(&<Self as Encode>::ENCODING);
+}
+
 pub type CVTimeStampFlags = u64;
 
 pub const kCVTimeStampVideoTimeValid: CVTimeStampFlags = 1 << 0;
@@ -1659,6 +1723,23 @@ pub struct CVSMPTETime {
     pub frames: i16,
 }
 
+unsafe impl Encode for CVSMPTETime {
+    const ENCODING: Encoding = Encoding::Struct(
+        "CVSMPTETime",
+        &[
+            i16::ENCODING,
+            i16::ENCODING,
+            u32::ENCODING,
+            u32::ENCODING,
+            u32::ENCODING,
+            i16::ENCODING,
+            i16::ENCODING,
+            i16::ENCODING,
+            i16::ENCODING,
+        ],
+    );
+}
+
 pub type CVSMPTETimeType = u32;
 
 pub const kCVSMPTETimeType24: CVSMPTETimeType = 0;
diff --git a/core-foundation-sys/Cargo.toml b/core-foundation-sys/Cargo.toml
index 81ed52a1f..be52bcbea 100644
--- a/core-foundation-sys/Cargo.toml
+++ b/core-foundation-sys/Cargo.toml
@@ -7,8 +7,6 @@ version = "0.8.6"
 authors = ["The Servo Project Developers"]
 license = "MIT OR Apache-2.0"
 
-[dependencies]
-
 [features]
 mac_os_10_7_support = [] # backwards compatibility
 mac_os_10_8_features = [] # enables new features
diff --git a/core-graphics-types/Cargo.toml b/core-graphics-types/Cargo.toml
index ce4598a0e..18c8a6c44 100644
--- a/core-graphics-types/Cargo.toml
+++ b/core-graphics-types/Cargo.toml
@@ -11,6 +11,7 @@ license = "MIT OR Apache-2.0"
 bitflags = "1.0"
 core-foundation = { path = "../core-foundation", version = "0.9" }
 libc = "0.2"
+objc2 = { version = "0.4.0", optional = true }
 
 [package.metadata.docs.rs]
 default-target = "x86_64-apple-darwin"
diff --git a/core-graphics-types/src/base.rs b/core-graphics-types/src/base.rs
index 4d8723319..33abaa43e 100644
--- a/core-graphics-types/src/base.rs
+++ b/core-graphics-types/src/base.rs
@@ -12,8 +12,6 @@
 #![allow(non_camel_case_types)]
 #![allow(non_upper_case_globals)]
 
-use libc;
-
 #[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "aarch64"))]
 pub type boolean_t = libc::c_int;
 #[cfg(target_arch = "x86_64")]
diff --git a/core-graphics-types/src/geometry.rs b/core-graphics-types/src/geometry.rs
index de94b0da5..16ee09d32 100644
--- a/core-graphics-types/src/geometry.rs
+++ b/core-graphics-types/src/geometry.rs
@@ -10,6 +10,8 @@
 use base::CGFloat;
 use core_foundation::base::TCFType;
 use core_foundation::dictionary::CFDictionary;
+#[cfg(feature = "objc2")]
+use objc2::encode::{Encode, Encoding};
 
 pub const CG_ZERO_POINT: CGPoint = CGPoint { x: 0.0, y: 0.0 };
 
@@ -39,6 +41,11 @@ pub struct CGSize {
     pub height: CGFloat,
 }
 
+#[cfg(feature = "objc2")]
+unsafe impl Encode for CGSize {
+    const ENCODING: Encoding = Encoding::Struct("CGSize", &[CGFloat::ENCODING, CGFloat::ENCODING]);
+}
+
 impl CGSize {
     #[inline]
     pub fn new(width: CGFloat, height: CGFloat) -> CGSize {
@@ -61,6 +68,11 @@ pub struct CGPoint {
     pub y: CGFloat,
 }
 
+#[cfg(feature = "objc2")]
+unsafe impl Encode for CGPoint {
+    const ENCODING: Encoding = Encoding::Struct("CGPoint", &[CGFloat::ENCODING, CGFloat::ENCODING]);
+}
+
 impl CGPoint {
     #[inline]
     pub fn new(x: CGFloat, y: CGFloat) -> CGPoint {
@@ -80,6 +92,11 @@ pub struct CGRect {
     pub size: CGSize,
 }
 
+#[cfg(feature = "objc2")]
+unsafe impl Encode for CGRect {
+    const ENCODING: Encoding = Encoding::Struct("CGRect", &[CGPoint::ENCODING, CGSize::ENCODING]);
+}
+
 impl CGRect {
     #[inline]
     pub fn new(origin: &CGPoint, size: &CGSize) -> CGRect {
@@ -145,6 +162,21 @@ pub struct CGAffineTransform {
     pub ty: CGFloat,
 }
 
+#[cfg(feature = "objc2")]
+unsafe impl Encode for CGAffineTransform {
+    const ENCODING: Encoding = Encoding::Struct(
+        "CGAffineTransform",
+        &[
+            CGFloat::ENCODING,
+            CGFloat::ENCODING,
+            CGFloat::ENCODING,
+            CGFloat::ENCODING,
+            CGFloat::ENCODING,
+            CGFloat::ENCODING,
+        ],
+    );
+}
+
 impl CGAffineTransform {
     #[inline]
     pub fn new(
diff --git a/core-graphics-types/src/lib.rs b/core-graphics-types/src/lib.rs
index 94a4eb979..e58848a6b 100644
--- a/core-graphics-types/src/lib.rs
+++ b/core-graphics-types/src/lib.rs
@@ -8,7 +8,8 @@
 // except according to those terms.
 
 extern crate core_foundation;
-extern crate libc;
+#[cfg(feature = "objc2")]
+extern crate objc2;
 
 pub mod base;
 pub mod geometry;
diff --git a/core-text/src/font.rs b/core-text/src/font.rs
index 6df9750ba..67662e9d2 100644
--- a/core-text/src/font.rs
+++ b/core-text/src/font.rs
@@ -206,7 +206,7 @@ pub fn new_ui_font_for_language(
     unsafe {
         let font_ref = CTFontCreateUIFontForLanguage(
             ui_type,
-            size,
+            size as CGFloat,
             language
                 .as_ref()
                 .map(|x| x.as_concrete_TypeRef())