which isn't a async function. I just wonder why in Xcode 15 it needs await while in Xcode 16 it doesn't?
Maybe it has something to do with changes with actor? I noticed that if I mark test1 with @MainActor, both Xcode 15 and 16 don't require me to use await. Is it because NotificationCenter.default.notifications now runs on MainActor by default?
The reason is didBecomeActiveNotification is bounded to UIApplication which is MainActor isolated class.
Declaration is different from swift 6 and before it
this is swift 6 declaration
extension UIApplication {
nonisolated public class let willEnterForegroundNotification: NSNotification.Name
nonisolated public class let didFinishLaunchingNotification: NSNotification.Name
nonisolated public class let didBecomeActiveNotification: NSNotification.Name
nonisolated public class let willResignActiveNotification: NSNotification.Name
nonisolated public class let didReceiveMemoryWarningNotification: NSNotification.Name
}
and this is the original declaration
extension UIApplication {
public class let willEnterForegroundNotification: NSNotification.Name
public class let didFinishLaunchingNotification: NSNotification.Name
public class let didBecomeActiveNotification: NSNotification.Name
public class let willResignActiveNotification: NSNotification.Name
public class let didReceiveMemoryWarningNotification: NSNotification.Name
}
So before swift 6 these global variable was accidentally bounded to MainActor. And these is the reason why await kicks in.
And how do you get rid of the warning? The docs say to use compact or map to get the Sendable payload, but this didBecomeActiveNotification doesn't have userInfo.
NotificationCenter's documentation includes a discussion and solution to this issue.
Notification doesn’t conform to Sendable, because several of its members can’t be sendable, such as object and the userInfo dictionary. If you iterate over the notifications in this sequence, Xcode issues a warning about crossing an actor boundary. To handle this, use a map(_:) or compactMap(_:) to extract sendable properties of the notification, such as its name or sendable values from the userInfo dictionary.
The following macOS example calls notifications(named:object:) to receive an asynchronous sequence of didActivateApplicationNotification notifications from the shared NSWorkspace notification center. It then uses a compactMap(_:) to retrieve NSRunningApplication values from the notification’s userInfo dictionary, from which it gets localizedName strings. Since the String type conforms to Sendable , you can iterate over this type without a compiler warning.
for await appName in NSWorkspace.shared.notificationCenter.notifications (
named: NSWorkspace.didActivateApplicationNotification)
.compactMap ({ notification in
guard let appInfo = notification.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication,
let name = appInfo.localizedName else { return nil as String? }
return name
})
{
print("Application activated: \(appName)")
}