SwiftQA Random

When are unsafe pointers justified?

What you’re giving up

  • No bounds checking
  • No ARC
  • No type safety (especially UnsafeRawPointer)
  • No optionality/nil-safety guarantees

Also invisible to Sendable checking — a hole in concurrency safety.

When it’s actually justified

  1. C/Objective-C interop where the API demands raw pointers.
  2. Performance-critical, hot-path code where bounds checking is a measured, real bottleneckUnsafeBufferPointer used with withUnsafeBufferPointer.
  3. Implementing your own low-level data structure or memory pool.
  4. Reinterpreting memory across type boundaries — e.g. withUnsafeBytes(of:).
  5. FFI with other languages generally.

When it’s NOT justified

  • “It might be faster” without profiling.
  • Avoiding Optional unwrapping ceremony.
  • Bridging between Swift types that already have safe conversion paths.
  • “I don’t want to deal with Sendable errors.”

The discipline once you’ve decided it’s justified

  • Scope the unsafe region as tightly as possible.
  • Never let an unsafe pointer outlive the closure/scope that produced it.
  • Document the invariant you’re relying on.
  • Prefer the most specific unsafe type available.

One-liner if pressed: “Unsafe pointers are justified at genuine boundaries where Swift’s safety model doesn’t apply anyway — C/Objective-C interop, raw byte-level reinterpretation, or hand-rolled low-level data structures — and, more rarely, in hot paths where profiling shows bounds-checking or ARC overhead is a real bottleneck; anywhere else, reaching for them trades away compiler-enforced safety for a convenience or perceived performance win that usually isn’t real.”