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?
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
}