« Calculate Text Sizes | Home | Use text fields for n… »

The order of events in Xojo

When to initialize what is always a good question. Doing a custom constructor for Application, a Window or Control allows you to initialize some things before Xojo does some setup steps. For example if you like to have custom delegates for Cocoa frameworks, like our NSApplicationDelegateMBS class. The MBS Plugin registration can also either go into the constructor or App.Open event.

The constructor of a control allows you to do initialization steps before the control is added to the window. The open event of the control then allows you to do things after the control is initialized. And the open event of the window allows you to setup something after all controls are setup, e.g. connect a window splitter to the left and right controls. With destructor, we have a way to cleanup when something closed. You should know that the close event for a window fires, when the window is closed in the GUI. But the window object may live much longer and still be referenced somewhere else.

App.Constructor
App.Open
MyControl.Constructor
MyWindow.Constructor before Super.Constructor
MyControl.Open
MyWindow.Open
MyWindow.Constructor after Super.Constructor
App.HandleAppleEvent
App.NewDocument
MyWindow.Paint
MyControl.Paint
App.Activate
MyControl.Activate
MyWindow.Activate

Window constructor is listed twice here, because by calling the Super.Constructor inside ours and the Super.Constructor fires the open event. The built-in constructor of the window will setup the window and then call open events of the controls and open event of the window. You can have code in the constructor when it returns.

When the window is setup, the app will check if there are files passed to the app to open. The HandleAppleEvent event allows you to overwrite the built-in behavior on macOS. Then either NewDocument or OpenDocument events fires to process either some files to open or to start a new document.

Once the open code is done, the windows and controls can paint to show the first window. Then the app comes to front and activate events are broadcasted to the app itself and the active window with all controls.

Now close the application:

App.CancelClose
MyWindow.CancelClose
MyControl.Close
MyWindow.Close
MyWindow.Destructor
MyControl.Destructor
App.Close
App.Destructor

CancelClose event in app and window allow to show a warning dialog "Do you want to save changes?". Then controls and windows get closed. If also the last references are freed, destructor will run. But depending on when you remove references, this may be much later. If you put controls or windows in a dictionary for example, make sure you remove items in main thread. Otherwise you may get a ThreadAccessingUIException when the destructor runs. We sometimes also have code to update a window and I highly recommend to check ControlCount property before updating controls. So before accessing a control in another window, we verify whether ControlCount is greater than 0, before we e.g. access the listbox there. This allows user to close the window, while we still hold a reference to it from another window and still be able to update controls there if needed.

When the app finally closes app.Close and destructor run. Those a great places for cleanup like deleting of temporary files. Then the app exits. Please notice that Xojo doesn't walk over global properties in Modules or shared properties in classes or windows to set them to nil. Destructors there may do not run.

What impressions have you got? Any special cases you found?
03 10 21 - 10:11