Hello World

Your first Swift Cross Platform Android and iOS app

This HelloWorld example serves two purposes

  • it introduces the basics of developing with SCADE
  • it provides a quick way of checking if the installation was successful and all settings are configured correctly

Create project

  1. In the IDE, choose File | New | SCADE Project

  2. Enter the name of the project, HelloWorld1

  3. Expand the HelloWorld1 folder. You will see the following structure

    • products folder that contains the binaries (Android, iOS binaries once you ran your first compilation)
    • src folder that contains all the source code.
      • One artifact are pages, which contain UI and source code and are marked with a .page file extension
    • res folder that contains all the resources
    • start.swift contains the code executed upon startup of the application
    • . build contains the configuration of the project

    The directory hierachy starts after HelloWorld1, i.e. referencing files in code is done using /res/image1.bnp for example

Create your first Hello World page

  1. Open the main.page file by doubleclicking it.
  2. Drag a label into the page, set Hello World as the text
  3. Center it in the middle of the screen
  4. Don't forget to press Control + s to save the file

Run the project

This minimum project can be started and run. The running options are

  • the powerful, superfast SCADE OSX runtime (aka SCADE Simulator)
  • the original Android Simulator
  • the original iOS Simulator
  • as an Android app
  • as an iOS App

Let's start with the SCADE simulator. Its very productive and easy to use for fast development purposes.

  1. Click on the large rectangle button, the project launch selector button
  1. Select the Scade Simulator as the runtime for launching

  2. Press the Play button to run the app

  3. The app should launch successfully with a HelloWorld page being displayed.

Compile to Android and iOS

So know that we have a minimal app, lets compile them to iOS and Android

  1. Select Android x86 as the target

๐Ÿ‘

Choice of Android Simulator (called emulator in Android world)

Always use the x86 emulator, as the ARM emulator is much slower.

  1. Press the Play button to compile the app to Android
  • The first time you compile, it takes > 60 seconds to finish compilation
  • After the first time, compilation speed is much faster as only the changed binaries are recreated

Adding an OnClick event to app

As a next step, lets printout "Hello World" when we click on a button. A very simple enhancement.

  1. Let's add a button. Click and drag the button on the bottom of the screen and drop it there
  2. Center it by using Layout Horizontal Center and Layout Horizontal Fill space
  3. Now, lets add an event
    3.1 Go to the underlying source code located in the main.page.swift file
    3.2 Within the load method, create a local variable button1 that holds the reference to the button
let button1 = self.page!.getWidgetByName("button1") as! SCDWidgetsButton
  • self.page! is the (self) reference to the current page you just modified in the page editor
  • getWidgetByName is a method that returns the reference to a widget by name.
  • Then, we cast it to the respective class for strongly typed use of variables

Now that we have a reference to the button, lets add the event handler

button1.onClick.append(SCDWidgetsEventHandler{ _ in print ("Hello World") })
  • Append to the OnClick array to add event handlers
  • The SCDWidgetsEventHandler is our event handler for all general click events. It takes a closure as input, where we execute the print statement

Here the entire code

import ScadeKit

class MainPageAdapter: SCDLatticePageAdapter {

// page adapter initialization
override func load(_ path: String) {		
	super.load(path)
		
 let button1 = self.page!.getWidgetByName("button1") as! SCDWidgetsButton
 button1.onClick.append(SCDWidgetsEventHandler{
 	_ in 
	 let label = self.page!.getWidgetByName("label1") as! SCDWidgetsLabel			
   	label.text = "Swift on Android rocks"
		})
  }
}

Using model binding to set label

We support model view binding capabilities that allow you to link your model to your view control. That means you can link a variable in your Swift class to a visual control element attribute easily.

Any change in the variable will cause a change in the controls' attribute.

In this step, we provide a simple example by introducing a variable and binding the value of the variable to the label's text attribute:

  1. Add a variable labelText . Prefix with @objc dynamic and make sure a type is assigned
import ScadeKit

class MainPageAdapter: SCDLatticePageAdapter {

	@objc dynamic var labelText : String = "Hello World"
	
	// page adapter initialization
	override func load(_ path: String) {		
		super.load(path)
		
		let button1 = self.page!.getWidgetByName("button1") as! SCDWidgetsButton
		button1.onClick.append(SCDWidgetsEventHandler{
			_ in 
				self.labelText = "Swift on Android rocks"
		})
	}
}
  1. Bind the variable to the labels
    2.1 go to the binding tab of the page editor
    2.2 link labelText to the label called label1

Common gotchas and troubleshooting

  1. You forgot to save the code/page and the changes did not show up. Use Control + s to save. Autosaving mode also ask you if you want to save if you didn't.

  2. Binding doesnt work. You forgot to use @objc dynamic keyword for variables you want to bind to. The compiler warns you about this.

  3. Binding doesnt work because you changed variables name or type and the binding is not valid anymore. Delete the invalid bindings in the binding tab. Invalid bindings are shown in the panel.

New user issues

This chapter lists the most common issues new users run into.

CRASH HANDLED; Application has crashed due

Many users are puzzled by this error message. It sounds dramatic, but all it says is there is a programming issues in your code and the app has stopped working.

Our suggestion is to look at the console output and analyze it for the root cause.

Invalid name/typo in getWidgetByName

The root cause is a common typo:

  1. You are using getWidgetByName to get a reference to a control. The names are case sensitive, and sometimes the name is simply misspelled. In our example, its spelled Button1 but the correct name is buttton1

  2. This caused getWidgetByName to return nil while casting it (using mandatory cast as!) to SCDWidgetsButton, which is resulting in the the below message
    unexpectedly found nil while unwrapping an Optional Value

As stated above, this is a simple message saying your app has stopped working.

To fix this, just change Button1 to button1 in getWidgetByName

Binding issues

When you use bindings, and change the source of the binding by changing the name of the variable, its type or its hierarchy, or you change the location of the target by for instance moving the control, you binding will become invalid.

You will always see binding errors in the panel:

Next reads