由于我是 Rust 的新手,我一直在阅读有关生命周期的内容,并且慢慢地了解它们,以及使用 Arc 和 Mutex 共享数据。我认为我这样做是正确的方法。
如果我正确理解错误(根据我所读到的内容),它告诉我回调可能比变量
b
的寿命更长,因此它会抛出错误。我不确定的是,如何解决该错误?
注意:
AppWindow
、AppMenu
和AppState
是由slint库自动生成的。然而,它们的定义如下:
AppWindow
- pub struct AppWindow(VRc<ItemTreeVTable, InnerAppWindow>)
AppMenu
- pub struct AppMenu<'a>(&Pin<Rc<InnerAppMenu>>)
AppState
- pub struct AppState<'a>(&Pin<Rc<InnerAppState>>)
货物.toml
[dependencies]
slint = "1.8.0"
use std::sync::Arc;
slint::slint! {
import { Button } from "std-widgets.slint";
export component AppWindow inherits Window {
Button { text: "Example"; }
}
export global AppMenu {
in-out property <bool> is-menu-opened: false;
}
export global AppState {
callback close-tab(bool);
callback active-project-changed(int);
in-out property <int> active-project: 0;
}
}
pub fn do_something(app_state: &AppState) {
app_state.set_active_project(1);
}
fn main() -> Result<(), slint::PlatformError> {
let app_window = Arc::new(AppWindow::new()?);
let a = app_window.clone();
let b = app_window.clone();
let app_menu_original: Arc<AppMenu> = Arc::new(a.global::<AppMenu>());
let app_state_original: Arc<AppState> = Arc::new(b.global::<AppState>()); // error is on this line
/* ... My callbacks to hook into slint ... */
let app_state = app_state_original.clone();
app_state_original.clone().on_active_project_changed(move |index| {
do_something(&app_state);
});
let app_state = app_state_original.clone();
app_state_original.clone().on_close_tab(move |value| {
do_something(&app_state);
});
/* ... The end of the program ... */
app_window.clone().run()?;
Ok(())
}
error[E0597]: `b` does not live long enough
--> packages/app/main.rs:46:52
|
44 | let b = app_window.clone();
| - binding `b` declared here
45 | let app_menu_original: Arc<AppMenu> = Arc::new(a.global::<AppMenu>());
46 | let app_state_original: Arc<AppState> = Arc::new(b.global::<AppState>());
| ^---------------------
| |
| borrowed value does not live long enough
| argument requires that `b` is borrowed for `'static`
...
120 | }
| - `b` dropped here while still borrowed
查看docs后,我发现还有一种访问
AppSate
的替代方法,那就是使用AppState::get(&app)
。
因此,在回调中我可以像这样使用
Arc::clone()
,而不是做一堆 AppState
的 AppState::get(&app)
:
let app = app_window.clone();
AppState::get(&app_window.clone()).on_active_project_changed(move |index| {
let app_state = AppState::get(&app);
do_something(&app_state);
});
这会将
AppSate
带入回调范围内。新代码现在如下所示:
use std::sync::Arc;
slint::slint! {
import { Button } from "std-widgets.slint";
export component AppWindow inherits Window {
Button { text: "Example"; }
}
export global AppMenu {
in-out property <bool> is-menu-opened: false;
}
export global AppState {
callback close-tab(bool);
callback active-project-changed(int);
in-out property <int> active-project: 0;
}
}
pub fn do_something(app_state: &AppState) {
app_state.set_active_project(1);
}
fn main() -> Result<(), slint::PlatformError> {
let app_window = Arc::new(AppWindow::new()?);
/* ... My callbacks to hook into slint ... */
let app = app_window.clone();
AppState::get(&app_window.clone()).on_active_project_changed(move |index| {
let app_state = AppState::get(&app);
do_something(&app_state);
});
let app = app_window.clone();
AppState::get(&app_window.clone()).on_close_tab(move |value| {
let app_state = AppState::get(&app);
do_something(&app_state);
});
/* ... The end of the program ... */
app_window.clone().run()?;
Ok(())
}