You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Instead of instantiating the `MainSplitViewController` the `UIStoryboard` will instantiate the initial View Controller and cast it to the `UINavigationController`.
88
93
89
94
Lastly, you have to create a new class inheriting from `UITableViewController`. Create a new **Cocoa Touch Class** and name it `SupplierTableViewController`.
@@ -104,11 +109,15 @@ Now that you have the first `UITableViewController` setup you will add code to l
104
109
Open the `SupplierTableViewController.swift` class and add the following import statements for full usage of the SDK:
105
110
106
111
```Swift
112
+
importUIKit
107
113
importSAPOData
108
114
importSAPFoundation
109
115
importSAPFiori
110
116
importSAPFioriFlows
111
117
importSAPCommon
118
+
importSAPOfflineOData
119
+
importESPMContainerFmwk
120
+
importSharedFmwk
112
121
113
122
```
114
123
@@ -133,19 +142,22 @@ Implement the following lines of code directly below the loading indicator prope
133
142
let destinations =FileConfigurationProvider("AppParameters").provideConfiguration().configuration["Destinations"] as! NSDictionary
134
143
135
144
// Retrieve the data service using the destinations dictionary and return it.
136
-
var dataService: ESPMContainer<OnlineODataProvider>? {
AlertHelper.displayAlert(with: NSLocalizedString("OData service is not reachable, please onboard again.", comment: ""), error: nil, viewController: self)
145
+
let destinations =FileConfigurationProvider("AppParameters").provideConfiguration().configuration["Destinations"] as! NSDictionary
146
+
147
+
var dataService: ESPMContainer<OfflineODataProvider>? {
AlertHelper.displayAlert(with: "OData service is not reachable, please onboard again.", error: nil, viewController: self)
139
150
returnnil
140
151
}
141
152
return dataService
142
153
}
143
154
144
155
```
145
156
146
-
> In case you're using an `ODataOfflineProvider` you have to change the above-mentioned code to use `ODataOfflineProvider` instead of `ODataOnlineProvider`. You have to also import `SAPOfflineOData` in addition to the `SAPOData` framework.
147
157
148
-
Because we're good citizens we want to use an app logger to log important information. Fortunately, SAP is offering a simple-to-use Logging API with the `SAPCommon` framework.
158
+
> In case you're using an `OfflineODataProvider` you have to change the above-mentioned code to use `OfflineODataProvider` instead of `OnlineODataProvider`. You have to also import `SAPOfflineOData` in addition to the `SAPOData` framework.
159
+
160
+
SAP offers a simple-to-use Logging API with the `SAPCommon` framework.
149
161
150
162
Implement the following line of code below the data service declaration:
151
163
@@ -163,7 +175,7 @@ private var suppliers = [Supplier]()
163
175
164
176
```
165
177
166
-
> From now on bigger code blocks are explained with inline comments. Read the inline comments carefully to fully understand what the code is doing and why we're implementing it.
178
+
> From now on bigger code blocks are explained with inline comments. Read the inline comments carefully to fully understand what the code is doing and why you're implementing it.
167
179
168
180
Loading all available suppliers is fairly easy using the generated data service. The generated code will handle all authentication and authorization challenges for you and the data service will construct all necessary requests to load, create and update entities in your backend.
169
181
@@ -224,7 +236,7 @@ First, implement two necessary `UITableViewDataSource` methods which are respons
224
236
```Swift
225
237
// MARK: - Table view data source
226
238
227
-
///We are only displaying one section for this screen, return 1.
239
+
///Only one section is displayed for this screen, return 1.
Using the `SAPFiori` framework allows you to choose from a large variety of `UITableViewCell` classes.
240
-
Because we're going to display suppliers, and those have a name, an address and probably contact data the `FUIContactCell` would be a perfect fit here. You can always use the **SAP Fiori Mentor** app, available in the App Store for iPad, to get an introduction to the control.
252
+
Because you're going to display suppliers, and those have a name, an address and probably contact data the `FUIContactCell` would be a perfect fit here. You can always use the **SAP Fiori Mentor** app, available in the App Store for iPad, to get an introduction to the control.
241
253
242
-
Before implementing the `tableView(_cellForRowAt:)` method responsible for dequeuing reusable cells and returning them to the `UITableView`, we want to register the `FUIContactCell` with the `UITableView` first. This is usually done in the `viewDidLoad()` method.
254
+
Before implementing the `tableView(_cellForRowAt:)` method responsible for dequeuing reusable cells and returning them to the `UITableView`, You need to register the `FUIContactCell` with the `UITableView` first. This is usually done in the `viewDidLoad()` method.
243
255
244
256
Implement the following lines of code before the `updateTableView()` method call in the `viewDidLoad()`:
245
257
246
258
```Swift
247
259
// Register the cell with the provided convenience reuse identifier.
// Because we're going to implement navigation later this cell has the disclosure indicator as accessory type indicating that navigation to the user.
283
+
//Navigation will be implemented later. This cell has the disclosure indicator as accessory type indicating that navigation to the user.
272
284
cell.accessoryType= .disclosureIndicator
273
285
274
286
return cell
@@ -303,7 +315,7 @@ Go back to the `tableView(_cellForRowAt:)` method and add the following lines of
303
315
cell.activityControl.addActivities(activities)
304
316
cell.activityControl.maxVisibleItems=3
305
317
306
-
// The FUIActivityControl provides you two different ways of reacting to user's interaction. One would be with a change handler the other would be with a delegate. Because I don't want the communication logic being in the tableView(_cellForRowAt:) method we're using the delegation way.
318
+
// The FUIActivityControl provides you two different ways of reacting to user's interaction. One would be with a change handler the other would be with a delegate. Because I don't want the communication logic being in the tableView(_cellForRowAt:) method you're using the delegation way.
307
319
cell.activityControl.delegate=self
308
320
309
321
```
@@ -354,8 +366,8 @@ Tapping on one of the `FUIActivityItem` will result in an alert dialogue showing
354
366
355
367
[ACCORDION-BEGIN [Step 5: ](Implement the Navigation Between the Supplier List and the Product List)]
356
368
357
-
In this step, we will implement a second `UITableViewController` displaying all products a supplier provides.
358
-
For this, we will use a storyboard segue to navigate to the `SupplierProductsTableViewController` and pass through the selected supplier.
369
+
In this step, you will implement a second `UITableViewController` displaying all products a supplier provides.
370
+
For this, you will use a storyboard segue to navigate to the `SupplierProductsTableViewController` and pass through the selected supplier.
359
371
360
372
> In case you're not familiar with segues please visit, and carefully read the official documentation before continuing. [Using Segues](https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/UsingSegues.html)
361
373
@@ -389,9 +401,9 @@ var supplier: Supplier!
389
401
390
402
```
391
403
392
-
Next, we will implement the `prepare(:for:sender:)` method which is responsible for making necessary preparations before the navigation is fully executed. In our case, we will pass the selected supplier to the `SupplierProductsTableViewController`.
404
+
Next, you will implement the `prepare(:for:sender:)` method which is responsible for making necessary preparations before the navigation is fully executed. In our case, you will pass the selected supplier to the `SupplierProductsTableViewController`.
393
405
394
-
Implement the `prepare(:for:sender:)` method:
406
+
Implement the `prepare(:for:sender:)` method in `SupplierTableViewController`:
@@ -431,16 +443,20 @@ You can now navigate back and forth between the `SupplierTableViewController` an
431
443
432
444
[ACCORDION-BEGIN [Step 6: ](Implement the loading and displaying of supplier-specific products)]
433
445
434
-
This view is similar to the `SupplierTableViewController` but instead of fetching all products, we will fetch supplier-specific products. To achieve that, we again can utilize the OData APIs. `SAPOData` provides the possibility to create so-called `DataQuery` objects which can define typical OData arguments for a backend call.
446
+
This view is similar to the `SupplierTableViewController` but instead of fetching all products, you will fetch supplier-specific products. To achieve that, you again can utilise the OData APIs. `SAPOData` provides the possibility to create so-called `DataQuery` objects which can define typical OData arguments for a backend call.
435
447
436
-
First, we need to make the needed import statements for that class:
448
+
First, you need to make the needed import statements for that class:
437
449
438
450
```Swift
439
451
importSAPOData
440
452
importSAPFoundation
441
453
importSAPFiori
442
454
importSAPFioriFlows
443
455
importSAPCommon
456
+
importESPMContainerFmwk
457
+
importSharedFmwk
458
+
importSAPOfflineOData
459
+
444
460
445
461
```
446
462
@@ -457,10 +473,9 @@ Add a couple of class properties necessary for the data service instance and the
457
473
// The available destinations from Mobile Services are hold in the FileConfigurationProvider. Retrieve it to find the correct data service
458
474
let destinations =FileConfigurationProvider("AppParameters").provideConfiguration().configuration["Destinations"] as! NSDictionary
459
475
460
-
// Retrieve the data service using the destinations dictionary and return it.
461
-
var dataService: ESPMContainer<OnlineODataProvider>? {
AlertHelper.displayAlert(with: NSLocalizedString("OData service is not reachable, please onboard again.", comment: ""), error: nil, viewController: self)
476
+
var dataService: ESPMContainer<OfflineODataProvider>? {
@@ -486,7 +501,7 @@ var loadingIndicator: FUILoadingIndicatorView?
486
501
487
502
Let's load some data!
488
503
489
-
We're using the same style we've used in the `SupplierTableViewController`. Implement the following two methods and read the inline comments carefully because you will see that we utilize the `DataQuery` object for making a filter as well as an expand.
504
+
You're using the same style you've used in the `SupplierTableViewController`. Implement the following two methods and read the inline comments carefully because you will see that you utilise the `DataQuery` object for making a filter as well as an expand.
490
505
491
506
> If you're not familiar with those OData specific terms please make yourself familiar with the OData specification:
492
507
@@ -539,7 +554,7 @@ override func viewDidLoad() {
539
554
540
555
```
541
556
542
-
We know that the products contain images for each product, it would be nice to display them as well, but to do so we have to write a little bit of code to make that happen.
557
+
Products contain images for each product, it would be nice to display them as well, but to do so you have to write a little bit of code to make that happen.
543
558
544
559
First, implement a class property holding the image URLs of all products.
545
560
@@ -548,7 +563,7 @@ private var productImageURLs = [String]()
548
563
549
564
```
550
565
551
-
The user might want to scroll through the products even if the images are not fully loaded yet we have to implement a simple image cache as well as a placeholder image to keep the performance of the table stable.
566
+
The user might want to scroll through the products even if the images are not fully loaded yet you have to implement a simple image cache as well as a placeholder image to keep the performance of the table stable.
552
567
553
568
Add the following line of code directly below the `productImageURLs`:
Now we have the foundation for fetching and caching images. You were probably wondering where the mapping from the fetched products to the product image URLs happens. We will implement that now.
609
+
Now you have the foundation for fetching and caching images. You were probably wondering where the mapping from the fetched products to the product image URLs happens. You will implement that now.
595
610
596
611
Go back to the `loadData(:)` method and add the following line of code directly below the product assignment. Your `loadData(:)` should look like this now:
Like the last time we have to register a `SAPFiori` cell with the `UITableView`, but this time it is a `FUIObjectTableViewCell`. Add the following lines of code to the `viewDidLoad()` method right before the `updateTableView(:)` method call.
637
+
Like the last time you have to register a `SAPFiori` cell with the `UITableView`, but this time it is a `FUIObjectTableViewCell`. Add the following lines of code to the `viewDidLoad()` method right before the `updateTableView(:)` method call.
Xcode will complain now because the `SupplierProductsTableViewController.swift` class is not conforming to the [`UISearchResultsUpdating`](https://developer.apple.com/documentation/uikit/uisearchresultsupdating) protocol.
731
746
732
-
Add an extension to your class, like we did in the `SupplierTableViewController`:
747
+
Add an extension to your class, like you did in the `SupplierTableViewController`:
// Get the searched-for term, note here that we don't have a time bouncer which waits for the user to finish its input. You could implement that if needed, for this simple example we do life searches for each character. I wouldn't recommend doing that over a large data set.
806
+
// Get the searched-for term, note here that you don't have a time bouncer which waits for the user to finish its input. You could implement that if needed, for this simple example you do life searches for each character. I wouldn't recommend doing that over a large data set.
0 commit comments