Search code examples
objective-cmultithreadingrustinteropunusernotification

Objective-C NSRunLoop & NotificationCenterDelegate not functional when spawned on Rust worker thread


I'm currently trying to use Rust C interop in order to send actional desktop notifications (using a modified version of this lib). The main goal here would be to handle these notification sending events on separate threads like so:

thread::spawn(move || unsafe {
  sys::sendNotification(
    NSString::from_str(&title).deref(),
    NSString::from_str(&message).deref(),
    NSString::from_str(&uri).deref(),
    NSString::from_str(&img.unwrap_or_default()).deref(),
  );
});

This would allow me to have multiple notification 'handlers' running at the same time (vs. just being able to have a single notification displayed at once), and would also allow my main process to run without being blocked. Given the nature of the program (web-scraper), I don't want scraping halted whenever a notification is being displayed.

That said, this approach is somewhat problematic because the underlying obj-c code relies on NSRunLoop to handle click events (e.g., user clicks on the action to open a web page) through the created NotificationCenterDelegate instance. Per my knowledge (feel free to fact-check me on this I'm not familiar with obj-c), NSRunLoops only operate on the main thread and this code is rendered useless if ran on a worker... The notification still sends in this scenario, but events aren't processed.

Is there a way to handle this that is more effective than running my scraping logic on a separate loop and sending notif-send events to the main thread for processing (which will probably be halted by a notification that I hadn't opened)?


Solution

  • Strictly speaking, there is (or can be) one NSRunLoop per thread, not only the main thread. But it's still the case that GUI stuff generally needs to run on the main thread.

    I recommend that you take the approach of running scraping on a separate thread. This is generally a good idea for any combination of long-running work and GUI — it ensures that the work cannot cause the UI to hang or hiccup.