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.

Sara Sampaio

Sara Sampaio

Author Since: March 10, 2022

0 0 votes
Article Rating
Subscribe
Notify of
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x