@@ -544,15 +544,107 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
544544 }
545545
546546 /// Add `state` to the state managed by the application.
547- /// See [`crate::Builder#manage`] for instructions.
548- fn manage < T > ( & self , state : T )
547+ ///
548+ /// This method can be called any number of times as long as each call
549+ /// refers to a different `T`.
550+ /// If a state for `T` is already managed, the function returns false and the value is ignored.
551+ ///
552+ /// Managed state can be retrieved by any command handler via the
553+ /// [`State`](crate::State) guard. In particular, if a value of type `T`
554+ /// is managed by Tauri, adding `State<T>` to the list of arguments in a
555+ /// command handler instructs Tauri to retrieve the managed value.
556+ ///
557+ /// # Panics
558+ ///
559+ /// Panics if state of type `T` is already being managed.
560+ ///
561+ /// # Mutability
562+ ///
563+ /// Since the managed state is global and must be [`Send`] + [`Sync`], mutations can only happen through interior mutability:
564+ ///
565+ /// ```rust,no_run
566+ /// use std::{collections::HashMap, sync::Mutex};
567+ /// use tauri::State;
568+ /// // here we use Mutex to achieve interior mutability
569+ /// struct Storage {
570+ /// store: Mutex<HashMap<u64, String>>,
571+ /// }
572+ /// struct Connection;
573+ /// struct DbConnection {
574+ /// db: Mutex<Option<Connection>>,
575+ /// }
576+ ///
577+ /// #[tauri::command]
578+ /// fn connect(connection: State<DbConnection>) {
579+ /// // initialize the connection, mutating the state with interior mutability
580+ /// *connection.db.lock().unwrap() = Some(Connection {});
581+ /// }
582+ ///
583+ /// #[tauri::command]
584+ /// fn storage_insert(key: u64, value: String, storage: State<Storage>) {
585+ /// // mutate the storage behind the Mutex
586+ /// storage.store.lock().unwrap().insert(key, value);
587+ /// }
588+ ///
589+ /// tauri::Builder::default()
590+ /// .manage(Storage { store: Default::default() })
591+ /// .manage(DbConnection { db: Default::default() })
592+ /// .invoke_handler(tauri::generate_handler![connect, storage_insert])
593+ /// // on an actual app, remove the string argument
594+ /// .run(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
595+ /// .expect("error while running tauri application");
596+ /// ```
597+ ///
598+ /// # Examples
599+ ///
600+ /// ```rust,no_run
601+ /// use tauri::{Manager, State};
602+ ///
603+ /// struct MyInt(isize);
604+ /// struct MyString(String);
605+ ///
606+ /// #[tauri::command]
607+ /// fn int_command(state: State<MyInt>) -> String {
608+ /// format!("The stateful int is: {}", state.0)
609+ /// }
610+ ///
611+ /// #[tauri::command]
612+ /// fn string_command<'r>(state: State<'r, MyString>) {
613+ /// println!("state: {}", state.inner().0);
614+ /// }
615+ ///
616+ /// tauri::Builder::default()
617+ /// .setup(|app| {
618+ /// app.manage(MyInt(0));
619+ /// app.manage(MyString("tauri".into()));
620+ /// // `MyInt` is already managed, so `manage()` returns false
621+ /// assert!(!app.manage(MyInt(1)));
622+ /// // read the `MyInt` managed state with the turbofish syntax
623+ /// let int = app.state::<MyInt>();
624+ /// assert_eq!(int.0, 0);
625+ /// // read the `MyString` managed state with the `State` guard
626+ /// let val: State<MyString> = app.state();
627+ /// assert_eq!(val.0, "tauri");
628+ /// Ok(())
629+ /// })
630+ /// .invoke_handler(tauri::generate_handler![int_command, string_command])
631+ /// // on an actual app, remove the string argument
632+ /// .run(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
633+ /// .expect("error while running tauri application");
634+ /// ```
635+ fn manage < T > ( & self , state : T ) -> bool
549636 where
550637 T : Send + Sync + ' static ,
551638 {
552- self . manager ( ) . state ( ) . set ( state) ;
639+ self . manager ( ) . state ( ) . set ( state)
553640 }
554641
555- /// Gets the managed state for the type `T`. Panics if the type is not managed.
642+ /// Retrieves the managed state for the type `T`.
643+ ///
644+ /// # Panics
645+ ///
646+ /// Panics if the state for the type `T` has not been previously [managed](Self::manage).
647+ /// Use [try_state](Self::try_state) for a non-panicking version.
556648 fn state < T > ( & self ) -> State < ' _ , T >
557649 where
558650 T : Send + Sync + ' static ,
@@ -565,7 +657,9 @@ pub trait Manager<R: Runtime>: sealed::ManagerBase<R> {
565657 . expect ( "state() called before manage() for given type" )
566658 }
567659
568- /// Tries to get the managed state for the type `T`. Returns `None` if the type is not managed.
660+ /// Attempts to retrieve the managed state for the type `T`.
661+ ///
662+ /// Returns `Some` if the state has previously been [managed](Self::manage). Otherwise returns `None`.
569663 fn try_state < T > ( & self ) -> Option < State < ' _ , T > >
570664 where
571665 T : Send + Sync + ' static ,
0 commit comments