10 Objective-C Features That Aren’t in Swift

By Jesse Feiler

If you are an experienced Objective-C developer, this list reminds you of some features you may be used to that aren’t available in Swift. In each case, workarounds and strategies for replacing your old tried-and-true Objective-C friends are provided. And don’t worry: In most cases, you’ll end up writing less code, and your code will be more robust.

Saying goodbye to header (.h) files

In Swift, the header (.h) files are gone. The .h and .m files for headers and bodies (originally called messages) of a class are consolidated into a single .swift file.

Saying farewell to dangling pointers (almost always)

It’s hard (but not impossible) to reference a dangling pointer in Swift. Over the last few years, Objective-C has also made such references more difficult, but they remain distinctly possible. You can avoid issues with these references if you make certain that pointers to instances are always set before they are used, and that they’re set to nil before the instance is deallocated. Swift uses very few pointers, so they can’t dangle.

Forgetting about uninitialized variables and properties

Swift requires initialization of declared properties, variables, and constants. This immediately removes a whole set of problems that can occur when you reference uninitialized variables and may either crash or cause unexpected (and frequently unrepeatable) errors.

Exploiting a common superclass like NSObject

Most objects in Objective-C are subclasses of NSObject; almost all of them conform to the NSObject protocol. Thus, collections such as NSArray and NSDictionary can contain objects of any kind as long as they are subclasses of NSObject. In Swift, the elements of an array or dictionary do not have a common superclass, but they do have to have a common type so that they can be manipulated. This is now your responsibility.

Managing type casting

Objective-C manages type casting where it can, but if your assumption about the correct cast differs from Objective-C’s, your code may crash. With Swift, you have to do the casting explicitly. However, Swift can infer a type from initial values of variables or constants, so, on balance, your code is more robust and you may actually need less of it because you can let Swift infer types for you.

Preferring closures to blocks

Blocks in Objective-C are like closures in other languages. In Swift, that function is provided by closures, and the documentation reflects this use.

Getting rid of legacy memory management

Although manual memory management with alloc and dealloc has been ­deprecated in Swift, much code still exists that either uses it or refers to it in comments and commented-out lines of code. If you are converting old code rather than writing new Swift code from scratch, it’s worthwhile to remove these vestiges of manual memory management. It’s very unlikely they will return.

Replacing property decorators

Instead of Objective-C’s property decorators, Swift has annotations in declarations. The mixture of attributes, such as readonly, strong, weak, and the like, is gone with Swift. The necessary information is encompassed in types.

Using Swift style to access class properties

Swift style uses dot syntax to reference objects within a class, structure, or enumeration. Remove any leftover bracket-based syntax.

Clarifying Swift access control

The privacy directives in Objective-C are handled differently in Swift. In Objective-C you use the following directives:

  • @private

  • @protected

  • @public

Declarations of methods and properties can also be placed both in the .h file or in a class extension of a .m file. This provides two disjoint ways of ­specifying visibility.

Swift has no .h or .m files and, therefore, no class extensions with hiddendeclarations. It has a single access control model using

  • public

  • private

  • internal

These are part of the language itself rather than being compiler directives.