How to Dereference an Unsafe Mutable Pointer in Swift

It can be frustrating if you are coming to Swift as an Objective-C developer. Do you ever find yourself thinking:

“I knew how to do this in Objective-C but I have no clue how to do it in Swift!”

Here is an example from when I was looking at the UIPopoverPresentationControllerDelegate protocol last week. When the system needs to reposition a popover, perhaps due to rotation, it calls a delegate method with the proposed view and CGRect. Here it is first in Objective-C:

- (void)popoverPresentationController:
  (nonnull UIPopoverPresentationController *)
  popoverPresentationController 
  willRepositionPopoverToRect:(inout nonnull CGRect *)rect
  inView:(inout UIView *__autoreleasing  __nonnull * __nonnull)view {

    *view = self.someView;
    *rect = self.someView.bounds;
}

Both parameters are pointers allowing you to access the proposed values and pass back new values if you wish. Getting and setting new values is as easy as dereferencing a pointer.

Now take a look at the same function in Swift:

func popoverPresentationController(
  popoverPresentationController:UIPopoverPresentationController,
  willRepositionPopoverToRect rect: UnsafeMutablePointer<CGRect>,
  inView view: AutoreleasingUnsafeMutablePointer<UIView?>) {

  // What to do here?
}

What is an UnsafeMutablePointer<CGRect> or an AutoreleasingUnsafeMutablePointer<UIView?> and how do you pass back new values for those parameters?

When two worlds collide

The problem in this case is not the fault of Swift. The confusing new syntax is to allow Swift code to interoperate with Objective-C and plain old C frameworks common in Cocoa and UIKit. An UnsafeMutablePointer is just a struct:

struct UnsafeMutablePointer<Memory>

You read this as a pointer to an object of type “Memory”. So looking again at our Swift signature:

The only difference between the two types of mutable pointer is the memory management used by the referenced storage. Either way to access the memory you must use the memory instance property:

/// Access the underlying raw memory, getting and setting values.
public var memory: Memory { get nonmutating set }

Note the use of a nonmutating setter which is enough to make your head spin. This property allows us to dereference the pointer to retrieve or set the value but does not change the pointer.

Some examples:

// Objective-C assuming CGRect *rect;
CGRect oldRect = *rect;
*rect = newRect;

// Swift assuming rect: UnsafeMutablePointer<CGRect>
oldRect = rect.memory
rect.memory = newRect

In brief, use rect.memory in Swift where you would have used *rect in Objective-C.

Knowing this we can easily translate our popover function to Swift:

func popoverPresentationController(
  popoverPresentationController:UIPopoverPresentationController,
  willRepositionPopoverToRect rect: UnsafeMutablePointer<CGRect>,
  inView view: AutoreleasingUnsafeMutablePointer<UIView?>) {

    view.memory = someView
    rect.memory = someView.bounds
}

All part of the Swift learning curve.

Further Reading

Never miss a post!

iOS Size Classes Cheat Sheet

Subscribe and get my free iOS Size Classes Cheat Sheet

Unsubscribe at any time.
No time to watch WWDC videos?

Sign up to get my iOS posts direct to your inbox and I will send you a free PDF of my iOS Size Classes Cheat Sheet.

Unsubscribe at any time.
Archives Categories
comments powered by Disqus