In this blog post, I share code snippets and examples from my YouTube session “Build beautiful, native mobile applications with SAP Fiori for iOS” as part of SAP’s Devtoberfest 2022.
The session’s highlight is leveraging the live preview capabilities within Xcode to explore and configure UI components without running the iOS app.
Here is the code for the ViewController
extension to use a view controller in a SwiftUI preview.
#if canImport(SwiftUI) && DEBUG
extension UIViewController {
private struct Preview: UIViewControllerRepresentable {
let viewController: UIViewController
func makeUIViewController(context: Context) -> UIViewController {
viewController
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}
public var preview: some View {
return Preview(viewController: self)
}
}
#endif
I explained how to configure the new Object Card View that is available since SAP BTP SDK for iOS version 8.0
import Foundation
import SAPFiori
#if canImport(SwiftUI) && DEBUG
import SwiftUI
class ObjectCardDemoViewController: FUIFormTableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(FUIObjectCardTableViewCell.self, forCellReuseIdentifier: FUIObjectCardTableViewCell.reuseIdentifier)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: FUIObjectCardTableViewCell.reuseIdentifier, for: indexPath as IndexPath) as! FUIObjectCardTableViewCell
cell.detailImageView.image = UIImage(named: "swiftui")
cell.title.text = "SwiftUI Demo"
cell.subtitle.text = "Devtoberfest"
cell.footnote.text = "Pretty cool"
cell.status.text = "Live Session in Progress"
cell.status.textColor = UIColor.preferredFioriColor(forStyle: .positiveLabel)
cell.primaryAction.isHidden = false
cell.primaryAction.setTitle("Learn More", for: .default)
cell.secondaryAction.isHidden = false
cell.secondaryAction.setTitle("Cancel", for: .default)
cell.overflowAction.isHidden = false
return cell
}
}
struct ObjectCardDemoViewController_Previews: PreviewProvider {
static var previews: some View {
UINavigationController(rootViewController: ObjectCardDemoViewController()).preview
}
}
#endif
Then I showed a more complex example of using FUIWhatsNewViewController
as an OnboardingStep
.
import Foundation
import SAPFiori
import SAPFioriFlows
class WhatsNewOnboardingStep: OnboardingStep {
let whatsNewDataSource = WhatsNewDemoDataSource()
let whatsNewDelegate = WhatsNewDemoDelegate()
func onboard(context: SAPFioriFlows.OnboardingContext, completionHandler: @escaping (SAPFioriFlows.OnboardingResult) -> Void) {
whatsNewDelegate.onboardingCompletionHandler = completionHandler
whatsNewDelegate.onboardingContext = context
let whatsNewController = FUIWhatsNewViewController()
whatsNewController.dataSource = whatsNewDataSource
whatsNewController.delegate = whatsNewDelegate
let navController = UINavigationController(rootViewController: whatsNewController)
context.presentationDelegate.present(navController) { optionalError in
()
}
}
func restore(context: SAPFioriFlows.OnboardingContext, completionHandler: @escaping (SAPFioriFlows.OnboardingResult) -> Void) {
()
}
func reset(context: SAPFioriFlows.OnboardingContext, completionHandler: @escaping () -> Void) {
()
}
}
class WhatsNewDemoDelegate: FUIWhatsNewViewControllerDelegate {
var onboardingContext: SAPFioriFlows.OnboardingContext! = nil
var onboardingCompletionHandler: ((SAPFioriFlows.OnboardingResult) -> Void)?
func whatsNewViewController(_ whatsNewViewController: SAPFiori.FUIWhatsNewViewController, willTransitionTo pendingViewControllerIndex: Int) {}
func whatsNewViewController(_ whatsNewViewController: SAPFiori.FUIWhatsNewViewController, didFinishAnimating finished: Bool, previousViewControllerIndex: Int, transitionCompleted completed: Bool) {}
func didFinishFlow(_ whatsNewViewController: SAPFiori.FUIWhatsNewViewController) {
onboardingContext.presentationDelegate.dismiss { [weak self] optionalError in
self?.onboardingCompletionHandler?(.success(self!.onboardingContext))
}
}
}
class WhatsNewDemoDataSource: FUIWhatsNewViewControllerDataSource {
var pages: [FUIWhatsNewDetailPageController] = []
init() {
let page1 = FUIWhatsNewDetailPageController()
page1.imageView.image = UIImage(systemName: "icloud.slash")
page1.titleLabel.text = "Offline Access"
page1.descriptionTextView.text = "All business data is available in offline. Data can be edited and be synced with backend once network connectivity is available for the device."
pages.append(page1)
let page2 = FUIWhatsNewDetailPageController()
page2.imageView.image = UIImage(systemName: "faceid")
page2.titleLabel.text = "Biometric Authentication"
page2.descriptionTextView.text = "Use Apple's FaceID for easy onboarding"
pages.append(page2)
}
func presentationViewControllers(for whatsNewViewController: FUIWhatsNewViewController) -> [UIViewController] {
return pages
}
func presentationIndex(for whatsNewViewController: FUIWhatsNewViewController) -> Int {
return 0
}
}
#if canImport(SwiftUI) && DEBUG
import SwiftUI
struct FUIWhatsNewViewControllerPreview: PreviewProvider {
static let whatsNewDataSource = WhatsNewDemoDataSource()
static let whatsNewDelegate = WhatsNewDemoDelegate()
static var controller: SAPFiori.FUIWhatsNewViewController {
let whatsNewController = FUIWhatsNewViewController()
whatsNewController.dataSource = whatsNewDataSource
whatsNewController.delegate = whatsNewDelegate
return whatsNewController
}
static var previews: some View {
UINavigationController(rootViewController: controller).preview
}
}
#endif
I hope you find the examples helpful.
Subscribe
Login
Please login to comment
0 Comments