Skip to Content

Explore the Generated App and OData Service

0 %
Explore the Generated App and OData Service

Explore the Generated App and OData Service

Build, run and examine the generated application to understand the OData service in detail.

You will learn

  • How to build and run the application generated in the last tutorial
  • Details about the OData service so you can extend the application in later tutorials


  • Development environment: Apple Mac running macOS Catalina or higher with Xcode 11 or higher
  • SAP Cloud Platform SDK for iOS: Version 4.0.10

Step 1: Build and run the generated application

Click the Run button to build and run the generated application:

Build and run

The Simulator app now launches.

Build and run

The application name is shown, with a description. You have the option to show a demo version of the application (this should be implemented by hand, as this is not generated by the iOS Assistant) or run the actual, live application.

In this tutorial, you use the live application. Tap the blue Start button to proceed.

The OAuth login screen of SAP Cloud Platform Mobile Services is shown. Enter your login credentials for the SAP Cloud Platform and tap the Log On button:

Build and run

The app now displays the initial Data Privacy acknowledgement page. Tap Allow to proceed.

Build and run

Choose a passcode to finish the onboarding process.

Note: The passcode is optional. If you don’t require an app passcode you can later delete the corresponding code in the generated OnboardingFlowProvider.swift class. The app passcode forces you to enter the passcode every time you start the app. If this bothers you during your development process you can change your simulator to always verify automatically.
To do so go to your simulator and in the menu Hardware -> Face ID and select Enrolled and Matching Face. The simulator now will simulate a matching face and pass the authentication.

Tap Next and confirm your passcode.

Build and run

After you confirmed your passcode by tapping the Done button, the application will ask you for permission to send notifications. You can tap on allow if you want to play with notifications later on.

Build and run

The first view you will see is an overview of the available Collections of the OData service:

Build and run
Log on to answer question
Step 2: Examine the generated application

If you tap on the Packages collection, you navigate to a Master list with all available Package entities:

Master screen

If you tap on one of the Package entities, you navigate to a Detail view which lists all the properties for the selected entity:

Detail screen

Notice the DeliveryStatus entry at the 5th row. If you tap on this, it will show the related DeliveryStatus entities for the current Package, based on the association in the OData service:

Detail screen

The OData service structure, and how the two entities are related, are explained in the next step.

Log on to answer question
Step 3: Introduction to the SDK's OData API

The generated application demonstrates the OData proxy classes are working, it enables you to browse their properties, and demonstrates push notifications and the various authentication mechanisms.

Note: The metadata XML for the sample OData service is provided below, but if you want to look at the metadata yourself in the future, you’ll first need to enable the developer features in the Safari browser. To do this, open Safari and click on the Safari menu, then Preferences, and click on the Advanced tab. In the Advanced tab you can enable the Show Develop menu in the menu bar option to enable the developer features. The Develop menu will now be visible in Safari, and accessing an XML resource – such as OData metadata – will display the raw XML.

Examine the OData service’s metadata, which can be accessed via$metadata

<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<edmx:Edmx Version="1.0" xmlns:edmx="">
  <edmx:DataServices m:DataServiceVersion="2.0" xmlns:m="">
    <Schema Namespace="" xmlns="" xmlns:d="" xmlns:m="">
      <EntityType Name="DeliveryStatusType">
          <PropertyRef Name="DeliveryStatusID"/>
        <Property MaxLength="36" Name="DeliveryStatusID" Nullable="false" Type="Edm.String"/>
        <Property MaxLength="36" Name="PackageID" Type="Edm.String"/>
        <Property MaxLength="256" Name="Location" Type="Edm.String"/>
        <Property Name="DeliveryTimestamp" Type="Edm.DateTime"/>
        <Property MaxLength="16" Name="StatusType" Type="Edm.String"/>
        <Property Name="Selectable" Type="Edm.Int32"/>
        <Property MaxLength="128" Name="Status" Type="Edm.String"/>
      <EntityType Name="PackagesType">
          <PropertyRef Name="PackageID"/>
        <Property MaxLength="36" Name="PackageID" Nullable="false" Type="Edm.String"/>
        <Property MaxLength="256" Name="Name" Type="Edm.String"/>
        <Property MaxLength="256" Name="Description" Type="Edm.String"/>
        <Property Name="Price" Precision="10" Scale="2" Type="Edm.Decimal"/>
        <NavigationProperty FromRole="PackagesPrincipal" Name="DeliveryStatus" Relationship="" ToRole="DeliveryStatusDependent"/>
      <Association Name="PackageDeliveryStatusType">
        <End Multiplicity="1" Role="PackagesPrincipal" Type=""/>
        <End Multiplicity="*" Role="DeliveryStatusDependent" Type=""/>
          <Principal Role="PackagesPrincipal">
            <PropertyRef Name="PackageID"/>
          <Dependent Role="DeliveryStatusDependent">
            <PropertyRef Name="PackageID"/>
      <EntityContainer Name="DeliveryService" m:IsDefaultEntityContainer="true">
        <EntitySet EntityType="" Name="DeliveryStatus"/>
        <EntitySet EntityType="" Name="Packages"/>
        <AssociationSet Association="" Name="PackageDeliveryStatus">
          <End EntitySet="Packages" Role="PackagesPrincipal"/>
          <End EntitySet="DeliveryStatus" Role="DeliveryStatusDependent"/>

The data model is fairly simple, containing two Entity Sets (or tables) called Packages and DeliveryStatus. Each entity (or record) in the set is identified as a PackagesType and DeliveryStatusType, respectively.

There is also an association between packages and delivery statuses, where a single package can have zero or more related delivery statuses. In the next tutorial, you will add a view that shows the related delivery statuses in a timeline, in ascending order (i.e. newest on top). The timeline is built using the SAP Fiori for iOS controls.

Data is retrieved from the cloud platform using the OData protocol, using the SDK’s SAPOData framework. Similar to executing SQL statements, the SDK provides a “fluent interface” or “method chaining” approach to constructing queries.

For example, a hypothetical SQL query to get all DeliveryStatus entities for a particular Package might look something like this:

FROM DeliveryStatus
WHERE DeliveryStatus.packageID == <selected package ID>

Using the SAPOData framework, the Swift code for this query looks like:

let query = DataQuery()
    .where(DeliveryStatusType.packageID == selectedPackageID)

The result of this query is an array of DeliveryStatusType objects.

Often, when querying for entities, you know ahead of time that you will need some of the associated entities. For example, when fetching the details for a given package, you may want to pre-fetch the associated delivery statuses for the package at the same time, so that you don’t need to query for them later; this can save time and bandwidth.

In SQL, this would be considered a JOIN operation:

FROM Packages
WHERE Packages.packageID = <selected package ID>
LEFT JOIN DeliveryStatus ON <abstracted, defined in association>

To do this using the OData API, you add an expand to the query:

let query = DataQuery()
    .where(PackagesType.packageID == selectedPackageID)

This loads the PackageType entity and all related child DeliveryStatusType entities at once. You can then access the related delivery status objects directly from the package object:

let deliveryStatuses = selectedPackage.deliveryStatus
print("Fetched \(deliveryStatuses.count) delivery status updates.")
Which of the two queries shown above gets all `DeliveryStatus` entities for a particular `Package`? Paste the query in below.

Next Steps

Back to top