xinatanil
xinatanil

Reputation: 634

Some NSNotification.Name constants are missing when enabling C++ interoperability

When enabling direct C++ interoperability in Xcode, this simple code below

NotificationCenter.default.addObserver(self,
                                       selector: #selector(subjectAreaDidChange(_:)),
                                       name: .AVCaptureDeviceSubjectAreaDidChange,
                                       object: nil)

gives me the following error

Type 'NSNotification.Name?' has no member 'AVCaptureDeviceSubjectAreaDidChange'

But if I switch C++ and Objective-C interoperability to just C / Objective-C then the code compiles without errors.

The issue seems to affect NSNotification.Name constants only from AVFoundation framework (although there maybe more).

Why do I get this error and how do I fix it?

Upvotes: 0

Views: 154

Answers (1)

iUrii
iUrii

Reputation: 13838

Short answer

It’s a known bug (https://forums.developer.apple.com/forums/thread/733693) for Xcode 15.

You can work it around by using raw strings of needed notifications:

NotificationCenter.default.addObserver(self,
                                       selector: #selector(subjectAreaDidChange),
                                       name: .init(rawValue: "AVCaptureDeviceSubjectAreaDidChangeNotification"),
                                       object: nil)

Long answer

If you look inside AVFoundation/AVCaptureDevice.h you can find:

AVF_EXPORT NSString *const AVCaptureDeviceSubjectAreaDidChangeNotification API_AVAILABLE(ios(5.0), macCatalyst(14.0), tvos(17.0)) API_UNAVAILABLE(macos, visionos) API_UNAVAILABLE(watchos);

The interoperability just looks for “Notification” suffix in exported strings and converts them to NSNotification.Name e.g.:

AVCaptureDeviceSubjectAreaDidChangeNotification -> NSNotification.Name.AVCaptureDeviceSubjectAreaDidChange

The same works for strings in your app:

// Test.h
extern NSString *const MyNotification;

// Test.m
NSString *const MyNotification = @"MyNotification";

Then you can write in your swift file:

let notification: NSNotification.Name = .My

But it works for C / Objective-C only and doesn't for C++ / Objective-C++ because the compiler doesn't generate appropriate properties in NSNotification.Name extension, for instance:

extension NSNotification.Name {
    ...    
    @available(iOS 5.0, *)
    public static let AVCaptureDeviceSubjectAreaDidChange: NSNotification.Name
}

Upvotes: 1

Related Questions