Preventing collisions in extensions with private Obj-C members

When adding an extension to Objective-C types, we run the risk of using the same method name as a private API, which can lead to subtle bugs: Inadvertently Extending Private API | Apple Developer Forums

Example from the above thread:

import HomeKit
extension HMHome
{
    // Same method signature as a private Obj-C method within HomeKit
    func roomWithUUID(inUUID: NSUUID) -> HMRoom?
    {
        // Implementation that's different to the private method,
        // which changes HomeKit's internal behaviour
    }
}

The approach I've seen to avoid this is with prefixing, e.g. renaming the above method to abc_roomWithUUID(inUUID: NSUUID), where abc is a common prefix used within your own project.

Could a different approach be to add the @nonobjc attribute to the method/extension instead? My hunch is that because the issue is specific to Objective-C types, hiding the extension from the Obj-C runtime would prevent the issue. Or are there other gotchas that mean manual prefixing is still preferred?

Yeah, if you use @nonobjc to ensure the methods are not exposed as ObjC selectors, then you don't need to be concerned about runtime collisions with pure Swift extensions.

2 Likes