Accessing application state after iced::run ends

Hi, I was wondering if the state of the applicaiton can be accessed outside the context of it. I’m planning create some pop-ups that should return the value based on the user input see proof of concept bellow:

use iced::widget::{button, column, text, Column};

#[derive(Default)]
struct App {
    last_pressed: String,
}

#[derive(Debug, Clone, Copy)]
enum Message {
    Button1,
    Button2,
    Button3,
}

impl App {
    pub fn update(&mut self, message: Message) {
        self.last_pressed = match message {
            Message::Button1 => "Button 1".to_string(),
            Message::Button2 => "Button 2".to_string(),
            Message::Button3 => "Button 3".to_string(),
        };
        
    }

    pub fn view(&self) -> Column<Message> {
        column![
            button("Button 1").on_press(Message::Button1),
            button("Button 2").on_press(Message::Button2),
            button("Button 3").on_press(Message::Button3),
            text(format!("Last pressed: {}", self.last_pressed)).size(30)
        ]
        .spacing(20)
    }
    
    pub fn new() -> Self{
        App { last_pressed: "".to_string() }
    }
}

fn main() -> iced::Result {
let _window = iced::application("Three Button App", 
    //updater
    App::update, 
    App::view)
    .window_size(iced::Size::new(300.0, 400.0));
    //.exit_on_close_request(false);
    

    let result: Result<(), iced::Error> = _window.run(); //the window gets consumed by run and no state can be accessed
    //accessing the state (in this case self.last_pressed) and returning it. 
    println!("User selected: {:?}", &result);
    result
}

I need the main function to have the return value of the string which was a part of the state of the application that closed (self.last_pressed in this example). I’m fairly new to rust so maybe there is a solution that I’m not seeing? Thanks in advance!

I’m pretty new to Iced, but I think you can use Application::run_with to initialize the context, put something like Arc<Mutex<...>> inside and retrieve it when exiting the program.

It was discussed on discord server and the maintainer answered it’s planed to implement a method like run_take or something, that returns Result<State, Error>.

Until it’s not completed yet you can try some workarounds:

  1. Create a channel or something, give the tx-part to update closure, use a subscription on CloseRequested + send your own message, handle this message with taking the value and sending it into the channel. Read the rx-part after run_ has completed and do anything with the received value.
  2. Duplicate the value (or use Arc<String>) to having the actual last_pressed and do something like this
let last_pressed = Rc::new(RefCell::<Arc<String>>::default());
let update = { 
    let last_pressed = last_pressed.clone();
    move |state: &mut State, message: Message| {
        let mut ref_mut = last_pressed.borrow_mut();
        state.update(message, &mut ref_mut)
    } 
};


....
....
....

pub fn update(&mut self, message: Message, last_pressed: &mut Arc<String>) {
    self.last_pressed = Arc::new( match message {
        Message::Button1 => "Button 1".to_string(),
        Message::Button2 => "Button 2".to_string(),
        Message::Button3 => "Button 3".to_string(),
    });
    *last_pressed = self.last_pressed.clone();
}